GithubHelp home page GithubHelp logo

Comments (3)

matthewlipski avatar matthewlipski commented on June 12, 2024

Which example are you referencing? The one from the docs or the one in the examples directory? Either way, the code in the docs hasn't been updated for 0.10.0 yet - you can use this as a base for your custom block for now:

// Alert.tsx

// The types of alerts that users can choose from
export const alertTypes = {
  warning: {
    icon: MdError,
    color: "#e69819",
    backgroundColor: {
      light: "#fff6e6",
      dark: "#805d20",
    },
  },
  error: {
    icon: MdCancel,
    color: "#d80d0d",
    backgroundColor: {
      light: "#ffe6e6",
      dark: "#802020",
    },
  },
  info: {
    icon: MdInfo,
    color: "#507aff",
    backgroundColor: {
      light: "#e6ebff",
      dark: "#203380",
    },
  },
  success: {
    icon: MdCheckCircle,
    color: "#0bc10b",
    backgroundColor: {
      light: "#e6ffe6",
      dark: "#208020",
    },
  },
} as const;

// The props for the Alert block
export const alertPropSchema = {
  textAlignment: defaultProps.textAlignment,
  textColor: defaultProps.textColor,
  type: {
    default: "warning" as const,
    values: ["warning", "error", "info", "success"] as const,
  },
} satisfies PropSchema;

const alertConfig = {
  type: "alert",
  propSchema: {
    textAlignment: defaultProps.textAlignment,
    textColor: defaultProps.textColor,
    type: {
      default: "warning",
      values: ["warning", "error", "info", "success"],
    },
  } as const,
  content: "inline",
} as const satisfies CustomBlockConfig;

// Component for the Alert block
export const Alert = (props: {
  block: BlockFromConfig<typeof alertConfig, InlineContentSchema, StyleSchema>;
  editor: BlockNoteEditor<
    BlockSchemaWithBlock<"alert", typeof alertConfig>,
    InlineContentSchema,
    StyleSchema
  >;
  contentRef: (node: HTMLElement | null) => void;
  theme: "light" | "dark";
}) => {
  const Icon = alertTypes[props.block.props.type].icon;

  return (
    <div
      className={"alert"}
      style={{
        ...alertStyles,
        backgroundColor:
          alertTypes[props.block.props.type].backgroundColor[props.theme],
      }}>
      {/*Icon which opens a menu to choose the Alert type*/}
      <Menu zIndex={99999}>
        <Menu.Target>
          {/*Icon wrapper to change the color*/}
          <div
            className={"alert-icon-wrapper"}
            style={{
              ...alertIconWrapperStyles,
              backgroundColor: alertTypes[props.block.props.type].color,
            }}
            contentEditable={false}>
            {/*Icon itself*/}
            <Icon
              className={"alert-icon"}
              style={{
                color:
                  alertTypes[props.block.props.type].backgroundColor[
                    props.theme
                  ],
              }}
              size={32}
            />
          </div>
        </Menu.Target>
        {/*Dropdown to change the Alert type*/}
        <Menu.Dropdown>
          <Menu.Label>Alert Type</Menu.Label>
          <Menu.Divider />
          {Object.entries(alertTypes).map(([key, value]) => {
            const ItemIcon = value.icon;

            return (
              <Menu.Item
                key={key}
                icon={<ItemIcon color={value.color} />}
                onClick={() =>
                  props.editor.updateBlock(props.block, {
                    type: "alert",
                    props: { type: key as keyof typeof alertTypes },
                  })
                }>
                {key.slice(0, 1).toUpperCase() + key.slice(1)}
              </Menu.Item>
            );
          })}
        </Menu.Dropdown>
      </Menu>
      {/*Rich text field for user to type in*/}
      <div style={inlineContentStyles} ref={props.contentRef} />
    </div>
  );
};

// Function which creates the Alert block itself, where the component is styled
// correctly with the light & dark theme
export const createAlertBlock = (theme: "light" | "dark") =>
  createReactBlockSpec(alertConfig, {
    render: (props) => <Alert {...props} theme={theme} />,
  });

export const getBlockSpecs = (theme: "light" | "dark") =>
  ({
    ...defaultBlockSpecs,
    alert: createAlertBlock(theme),
  } satisfies BlockSpecs);
export const blockSchema = {
  ...defaultBlockSchema,
  alert: alertConfig,
} satisfies BlockSchema;

// Slash menu item to insert an Alert block
export const getInsertAlert = (theme: "light" | "dark") =>
  ({
    name: "Alert",
    execute: (editor) => {
      editor.insertBlocks(
        [
          {
            type: "alert",
          },
        ],
        editor.getTextCursorPosition().block,
        "after"
      );
      editor.setTextCursorPosition(editor.getTextCursorPosition().nextBlock!);
    },
    aliases: [
      "alert",
      "notification",
      "emphasize",
      "warning",
      "error",
      "info",
      "success",
    ],
    group: "Other",
    icon: <RiAlertFill />,
    hint: "Used to emphasize text",
  } satisfies ReactSlashMenuItem<typeof blockSchema>);

const alertStyles = {
  display: "flex",
  justifyContent: "center",
  alignItems: "center",
  flexGrow: 1,
  borderRadius: "4px",
  height: "48px",
  padding: "4px",
} as const;

const alertIconWrapperStyles = {
  borderRadius: "16px",
  display: "flex",
  justifyContent: "center",
  alignItems: "center",
  marginLeft: "12px",
  marginRight: "12px",
  height: "18px",
  width: "18px",
  userSelect: "none",
  cursor: "pointer",
} as const;

const inlineContentStyles = {
  flexGrow: "1",
};
// App.tsx

export function App() {
  const editor = useBlockNote({
    domAttributes: {
      editor: {
        class: "editor",
        "data-test": "editor",
      },
    },
    blockSpecs: getBlockSpecs("light"),
    slashMenuItems: [
      ...getDefaultReactSlashMenuItems(blockSchema),
      getInsertAlert("light"),
    ],
    uploadFile: uploadToTmpFilesDotOrg_DEV_ONLY,
  });

  // Give tests a way to get prosemirror instance
  (window as WindowWithProseMirror).ProseMirror = editor?._tiptapEditor;

  return <BlockNoteView className="root" editor={editor} />;
}

from blocknote.

CharlieCho2017 avatar CharlieCho2017 commented on June 12, 2024

Thank you. Fixed it.

from blocknote.

YousefED avatar YousefED commented on June 12, 2024

@matthewlipski we've fixed the code in the docs, right?

from blocknote.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.