@netless/fastboard 0.0.7 → 0.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs.js","sources":["../src/behaviors/register-apps.ts","../src/internal/helpers.ts","../src/i18n/index.ts","../src/internal/mount-whiteboard.ts","../node_modules/.pnpm/object-assign@4.1.1/node_modules/object-assign/index.js","../node_modules/.pnpm/react@17.0.2/node_modules/react/cjs/react-jsx-runtime.production.min.js","../node_modules/.pnpm/react@17.0.2/node_modules/react/jsx-runtime.js","../react/jsx-runtime","../src/icons/index.tsx","../src/theme/index.ts","../src/components/Toolbar/icons/Apps.tsx","../src/components/Toolbar/icons/Arrow.tsx","../src/components/Toolbar/icons/Circle.tsx","../src/components/Toolbar/icons/Clean.tsx","../src/components/Toolbar/icons/Clicker.tsx","../src/components/Toolbar/icons/Collapse.tsx","../src/components/Toolbar/icons/Diamond.tsx","../src/components/Toolbar/icons/Down.tsx","../src/components/Toolbar/icons/Eraser.tsx","../src/components/Toolbar/icons/Expand.tsx","../src/components/Toolbar/icons/Line.tsx","../src/components/Toolbar/icons/Pencil.tsx","../src/components/Toolbar/icons/Rectangle.tsx","../src/components/Toolbar/icons/Selector.tsx","../src/components/Toolbar/icons/SpeechBalloon.tsx","../src/components/Toolbar/icons/Star.tsx","../src/components/Toolbar/icons/Text.tsx","../src/components/Toolbar/icons/Triangle.tsx","../src/components/Toolbar/icons/Up.tsx","../src/components/Toolbar/icons/index.ts","../src/components/Toolbar/components/Button.tsx","../src/components/Toolbar/components/CutLine.tsx","../src/components/Toolbar/hooks.ts","../src/components/Toolbar/const.ts","../src/components/Toolbar/components/UpDownButtons.tsx","../src/components/Toolbar/components/ApplianceButtons.tsx","../src/components/Toolbar/components/assets/vscode.png","../src/components/Toolbar/components/assets/geogebra.png","../src/components/Toolbar/components/assets/countdown.png","../src/components/Toolbar/components/AppsButton.tsx","../src/components/Toolbar/components/ColorBox.tsx","../src/components/Toolbar/components/Slider.tsx","../src/components/Toolbar/components/PencilButton.tsx","../src/components/Toolbar/components/TextButton.tsx","../src/components/Toolbar/components/ShapesButton.tsx","../src/components/Toolbar/Content.tsx","../src/components/Toolbar/Toolbar.tsx","../src/icons/Undo.tsx","../src/icons/Redo.tsx","../src/components/RedoUndo.tsx","../src/icons/Minus.tsx","../src/icons/Plus.tsx","../src/icons/Reset.tsx","../src/components/ZoomControl.tsx","../src/icons/FilePlus.tsx","../src/icons/ChevronLeft.tsx","../src/icons/ChevronRight.tsx","../src/components/PageControl.tsx","../src/components/Root.tsx","../src/internal/Instance.tsx","../src/behaviors/style.ts","../src/WhiteboardApp.ts","../src/components/PlayerControl/hooks.ts","../src/components/PlayerControl/icons/Loading.tsx","../src/components/PlayerControl/icons/Pause.tsx","../src/components/PlayerControl/icons/Play.tsx","../src/components/PlayerControl/icons/index.ts","../src/components/PlayerControl/components/Button.tsx","../src/components/PlayerControl/PlayerControl.tsx","../src/hooks.ts","../src/index.ts"],"sourcesContent":["import { WindowManager } from \"@netless/window-manager\";\n\nWindowManager.register({\n kind: \"Slide\",\n appOptions: {\n // turn on to show debug controller\n debug: false,\n },\n src: async () => {\n const app = await import(\"@netless/app-slide\");\n return app.default ?? app;\n },\n});\n\nWindowManager.register({\n kind: \"Monaco\",\n src: async () => {\n const app = await import(\"@netless/app-monaco\");\n return app.default ?? app;\n },\n});\nWindowManager.register({\n kind: \"Countdown\",\n src: async () => {\n const app = await import(\"@netless/app-countdown\");\n return app.default ?? app;\n },\n});\nWindowManager.register({\n kind: \"GeoGebra\",\n src: async () => {\n const app = await import(\"@netless/app-geogebra\");\n return app.default ?? app;\n },\n appOptions: {\n HTML5Codebase:\n \"https://flat-storage-cn-hz.whiteboard.agora.io/GeoGebra/HTML5/5.0/web3d\",\n },\n});\n","export function noop() {\n return;\n}\n\nexport function applyStyles(css: string) {\n const el = document.createElement(\"style\");\n el.appendChild(document.createTextNode(css));\n document.head.appendChild(el);\n return el;\n}\n\nexport function clamp(value: number, min: number, max: number) {\n return value < min ? min : value > max ? max : value;\n}\n\nexport function isEqualArray<T>(a: T[], b: T[]) {\n return a.length === b.length && a.every((e, i) => e === b[i]);\n}\n\nexport type TaskFn = () => Promise<void> | void;\n\nexport class Lock {\n running = false;\n private nextFn: TaskFn | null = null;\n schedule(fn: TaskFn) {\n if (this.running) {\n this.nextFn = fn;\n } else {\n this.running = true;\n Promise.resolve(fn()).then(this.step);\n }\n }\n private step = () => {\n if (this.nextFn) {\n const fn = this.nextFn;\n this.nextFn = null;\n Promise.resolve(fn()).then(this.step);\n } else {\n this.running = false;\n }\n };\n}\n","import i18next from \"i18next\";\nimport en from \"./en.json\";\nimport zhCN from \"./zh-CN.json\";\n\nexport type CreateI18nParams = {\n language?: string;\n};\n\nexport const createI18n = async (params: CreateI18nParams) => {\n const defaultLang = navigator.language || \"zh-CN\";\n const lng = params.language || defaultLang;\n\n await i18next.init({\n lng,\n resources: {\n en: en,\n \"zh-CN\": zhCN,\n },\n });\n\n return i18next;\n};\n","import type { MountParams } from \"@netless/window-manager\";\nimport type {\n JoinRoomParams,\n RoomCallbacks,\n WhiteWebSdkConfiguration,\n} from \"white-web-sdk\";\nimport type { Essentials, Language } from \"./Instance\";\n\nimport { WindowManager } from \"@netless/window-manager\";\nimport { DefaultHotKeys, WhiteWebSdk } from \"white-web-sdk\";\nimport { createI18n } from \"../i18n\";\n\nexport type SdkConfig = Omit<\n WhiteWebSdkConfiguration,\n \"useMobXState\" | \"disableNewPencil\" | \"disableMagixEventDispatchLimit\"\n>;\nexport type JoinRoom = Omit<\n JoinRoomParams,\n \"useMultiViews\" | \"disableMagixEventDispatchLimit\"\n> & { callbacks?: Partial<RoomCallbacks> };\nexport type ManagerConfig = Omit<MountParams, \"room\">;\n\nfunction ensureWindowManager(joinRoom: JoinRoom) {\n if (\n !joinRoom.invisiblePlugins ||\n !joinRoom.invisiblePlugins.includes(WindowManager)\n ) {\n joinRoom.invisiblePlugins = [\n ...(joinRoom.invisiblePlugins || []),\n WindowManager,\n ];\n }\n}\n\nexport const defaultHotKeys = {\n changeToSelector: \"s\",\n changeToLaserPointer: \"z\",\n changeToPencil: \"p\",\n changeToRectangle: \"r\",\n changeToEllipse: \"c\",\n changeToEraser: \"e\",\n changeToText: \"t\",\n changeToStraight: \"l\",\n changeToArrow: \"a\",\n changeToHand: \"h\",\n};\n\nexport async function mountWhiteboard(\n sdkConfig: SdkConfig,\n joinRoom: JoinRoom,\n managerConfig: ManagerConfig,\n language: Language\n): Promise<Essentials> {\n const sdk = new WhiteWebSdk({\n ...sdkConfig,\n useMobXState: true,\n });\n\n ensureWindowManager(joinRoom);\n joinRoom = { ...joinRoom };\n const callbacks = joinRoom.callbacks;\n delete joinRoom.callbacks;\n const joinRoomParams: JoinRoomParams = {\n floatBar: true,\n hotKeys: {\n ...DefaultHotKeys,\n ...defaultHotKeys,\n },\n ...joinRoom,\n useMultiViews: true,\n disableNewPencil: false,\n disableMagixEventDispatchLimit: true,\n };\n const room = await sdk.joinRoom(joinRoomParams, callbacks);\n\n const manager = await WindowManager.mount({\n cursor: true,\n debug: import.meta.env.DEV,\n ...managerConfig,\n room,\n });\n\n const i18n = await createI18n({ language });\n\n if (import.meta.env.DEV) {\n Object.assign(window, { sdk, room, manager });\n }\n\n return { sdk, room, manager, i18n };\n}\n","/*\nobject-assign\n(c) Sindre Sorhus\n@license MIT\n*/\n\n'use strict';\n/* eslint-disable no-unused-vars */\nvar getOwnPropertySymbols = Object.getOwnPropertySymbols;\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\nvar propIsEnumerable = Object.prototype.propertyIsEnumerable;\n\nfunction toObject(val) {\n\tif (val === null || val === undefined) {\n\t\tthrow new TypeError('Object.assign cannot be called with null or undefined');\n\t}\n\n\treturn Object(val);\n}\n\nfunction shouldUseNative() {\n\ttry {\n\t\tif (!Object.assign) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// Detect buggy property enumeration order in older V8 versions.\n\n\t\t// https://bugs.chromium.org/p/v8/issues/detail?id=4118\n\t\tvar test1 = new String('abc'); // eslint-disable-line no-new-wrappers\n\t\ttest1[5] = 'de';\n\t\tif (Object.getOwnPropertyNames(test1)[0] === '5') {\n\t\t\treturn false;\n\t\t}\n\n\t\t// https://bugs.chromium.org/p/v8/issues/detail?id=3056\n\t\tvar test2 = {};\n\t\tfor (var i = 0; i < 10; i++) {\n\t\t\ttest2['_' + String.fromCharCode(i)] = i;\n\t\t}\n\t\tvar order2 = Object.getOwnPropertyNames(test2).map(function (n) {\n\t\t\treturn test2[n];\n\t\t});\n\t\tif (order2.join('') !== '0123456789') {\n\t\t\treturn false;\n\t\t}\n\n\t\t// https://bugs.chromium.org/p/v8/issues/detail?id=3056\n\t\tvar test3 = {};\n\t\t'abcdefghijklmnopqrst'.split('').forEach(function (letter) {\n\t\t\ttest3[letter] = letter;\n\t\t});\n\t\tif (Object.keys(Object.assign({}, test3)).join('') !==\n\t\t\t\t'abcdefghijklmnopqrst') {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn true;\n\t} catch (err) {\n\t\t// We don't expect any of the above to throw, but better to be safe.\n\t\treturn false;\n\t}\n}\n\nmodule.exports = shouldUseNative() ? Object.assign : function (target, source) {\n\tvar from;\n\tvar to = toObject(target);\n\tvar symbols;\n\n\tfor (var s = 1; s < arguments.length; s++) {\n\t\tfrom = Object(arguments[s]);\n\n\t\tfor (var key in from) {\n\t\t\tif (hasOwnProperty.call(from, key)) {\n\t\t\t\tto[key] = from[key];\n\t\t\t}\n\t\t}\n\n\t\tif (getOwnPropertySymbols) {\n\t\t\tsymbols = getOwnPropertySymbols(from);\n\t\t\tfor (var i = 0; i < symbols.length; i++) {\n\t\t\t\tif (propIsEnumerable.call(from, symbols[i])) {\n\t\t\t\t\tto[symbols[i]] = from[symbols[i]];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn to;\n};\n","/** @license React v17.0.2\n * react-jsx-runtime.production.min.js\n *\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n'use strict';require(\"object-assign\");var f=require(\"react\"),g=60103;exports.Fragment=60107;if(\"function\"===typeof Symbol&&Symbol.for){var h=Symbol.for;g=h(\"react.element\");exports.Fragment=h(\"react.fragment\")}var m=f.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentOwner,n=Object.prototype.hasOwnProperty,p={key:!0,ref:!0,__self:!0,__source:!0};\nfunction q(c,a,k){var b,d={},e=null,l=null;void 0!==k&&(e=\"\"+k);void 0!==a.key&&(e=\"\"+a.key);void 0!==a.ref&&(l=a.ref);for(b in a)n.call(a,b)&&!p.hasOwnProperty(b)&&(d[b]=a[b]);if(c&&c.defaultProps)for(b in a=c.defaultProps,a)void 0===d[b]&&(d[b]=a[b]);return{$$typeof:g,type:c,key:e,ref:l,props:d,_owner:m.current}}exports.jsx=q;exports.jsxs=q;\n","'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n module.exports = require('./cjs/react-jsx-runtime.production.min.js');\n} else {\n module.exports = require('./cjs/react-jsx-runtime.development.js');\n}\n","import * as jsxRuntime from \"/home/runner/work/fastboard/fastboard/node_modules/react/jsx-runtime.js\"\nexport const jsx = jsxRuntime.jsx\nexport const jsxs = jsxRuntime.jsxs\nexport const Fragment = jsxRuntime.Fragment","import React from \"react\";\n\nexport interface IconPropsWithFallback {\n fallback: React.ReactElement;\n src?: string;\n alt?: string;\n}\n\nexport function Icon({ fallback, src, alt = \"[icon]\" }: IconPropsWithFallback) {\n return src ? <img src={src} alt={alt} title={alt} /> : fallback;\n}\n","import type { IconProps } from \"../types\";\n\nexport interface ThemeConfig {\n color: string;\n activeColor: string;\n backgroundColor: string;\n hoverBackgroundColor: string;\n}\n\nexport const light: ThemeConfig = {\n color: \"#5D5D5D\",\n activeColor: \"#3381FF\",\n backgroundColor: \"#fff\",\n hoverBackgroundColor: \"rgba(51, 129, 255, 0.1)\",\n};\n\nexport const dark: ThemeConfig = {\n ...light,\n color: \"#eee\",\n backgroundColor: \"#111\",\n};\n\nexport const themes = { light, dark };\n\nexport const getStroke = (props: IconProps) => {\n let config;\n if (props.theme) {\n config = themes[props.theme];\n } else {\n config = themes.light;\n }\n return props.active ? config.activeColor : config.color;\n};\n\nexport const TopOffset = [0, 11] as [number, number];\nexport const RightOffset = [0, 11] as [number, number];\n","import type { IconProps } from \"../../../types\";\n\nimport React from \"react\";\nimport { getStroke } from \"../../../theme\";\n\nexport const Apps = (props: IconProps) => {\n const stroke = getStroke(props);\n return (\n <svg viewBox=\"0 0 24 24\">\n <g fill={stroke}>\n <path d=\"M17.667 4.5h-3.334c-1.012 0-1.833.82-1.833 1.833V11.5h5.167c1.012 0 1.833-.82 1.833-1.833V6.333c0-1.012-.82-1.833-1.833-1.833Zm-3.334 1h3.334c.46 0 .833.373.833.833v3.334l-.006.104a.833.833 0 0 1-.827.729H13.5V6.333c0-.46.373-.833.833-.833Z\" />\n <path d=\"M6.333 19.5A1.833 1.833 0 0 1 4.5 17.667v-3.334c0-.525.221-1 .576-1.334a1.822 1.822 0 0 1-.576-1.332V8.333c0-1.012.82-1.833 1.833-1.833H10A1.5 1.5 0 0 1 11.5 8v4.5h4.167c.962 0 1.75.74 1.827 1.683l.006.15v3.334c0 1.012-.82 1.833-1.833 1.833Zm4.167-6H6.333a.833.833 0 0 0-.827.729l-.006.104v3.334c0 .46.373.833.833.833H10.5v-5Zm5.167 0H11.5v5h4.167c.46 0 .833-.373.833-.833v-3.334a.833.833 0 0 0-.833-.833ZM10 7.5H6.333a.833.833 0 0 0-.833.833v3.334c0 .46.373.833.833.833H10.5V8a.5.5 0 0 0-.41-.492L10 7.5Z\" />\n </g>\n </svg>\n );\n};\n","import type { IconProps } from \"../../../types\";\n\nimport React from \"react\";\nimport { getStroke } from \"../../../theme\";\n\nexport const Arrow = (props: IconProps) => {\n const stroke = getStroke(props);\n return (\n <svg viewBox=\"0 0 24 24\">\n <path\n fill={stroke}\n d=\"M19 5v6l-2.647-2.646L5.99 18.718l-.708-.708L15.645 7.646 13 5h6Z\"\n />\n </svg>\n );\n};\n","import type { IconProps } from \"../../../types\";\n\nimport React from \"react\";\nimport { getStroke } from \"../../../theme\";\n\nexport const Circle = (props: IconProps) => {\n const stroke = getStroke(props);\n return (\n <svg viewBox=\"0 0 24 24\">\n <rect\n width=\"15\"\n height=\"15\"\n x=\"4.5\"\n y=\"4.5\"\n fill=\"none\"\n stroke={stroke}\n rx=\"7.5\"\n />\n </svg>\n );\n};\n","import type { IconProps } from \"../../../types\";\n\nimport React from \"react\";\nimport { getStroke } from \"../../../theme\";\n\nexport const Clean = (props: IconProps) => {\n const stroke = getStroke(props);\n return (\n <svg viewBox=\"0 0 24 24\">\n <path\n fill={stroke}\n d=\"M9.754 11.99c0 1.856-.711 3.62-1.96 4.951l-.151.155h1.403l.855-.853h.707l.853.853h2.635l.094-.064a6.237 6.237 0 0 0 2.559-4.781l.005-.26h1a7.237 7.237 0 0 1-2.994 5.862l-.229.16-.277.083h-3l-.353-.146-.647-.647-.646.647-.354.146h-3l-.286-.91.214-.148a6.237 6.237 0 0 0 2.567-4.787l.005-.26h1Zm4.772-6.502v2l.35.039a2.98 2.98 0 0 1 2.644 2.78l.006.181h-8a2.98 2.98 0 0 1 2.65-2.961l.35-.039v-2h2Z\"\n />\n </svg>\n );\n};\n","import type { IconProps } from \"../../../types\";\n\nimport React from \"react\";\nimport { getStroke } from \"../../../theme\";\n\nexport const Clicker = (props: IconProps) => {\n const stroke = getStroke(props);\n return (\n <svg viewBox=\"0 0 24 24\">\n <g fill=\"none\">\n <path d=\"M0 0h24v24H0z\" />\n <path\n fill={stroke}\n d=\"m7 5.072 10.33 7.892-4.879.549 3.232 5.598-.866.5-3.233-5.597-2.914 3.95L7 5.072Z\"\n />\n </g>\n </svg>\n );\n};\n","import type { IconProps } from \"../../../types\";\n\nimport React from \"react\";\nimport { getStroke } from \"../../../theme\";\n\nexport const Collapse = (props: IconProps) => {\n const stroke = getStroke(props);\n return (\n <svg viewBox=\"0 0 24 24\">\n <path\n fill=\"none\"\n stroke={stroke}\n d=\"m8 10-2 2 2 2m10-8H6m12 12H6m12-4h-8m8-4h-8\"\n />\n </svg>\n );\n};\n","import type { IconProps } from \"../../../types\";\n\nimport React from \"react\";\nimport { getStroke } from \"../../../theme\";\n\nexport const Diamond = (props: IconProps) => {\n const stroke = getStroke(props);\n return (\n <svg viewBox=\"0 0 24 24\">\n <path\n fill=\"none\"\n stroke={stroke}\n d=\"M4.222 12 12 4.222 19.778 12 12 19.778z\"\n />\n </svg>\n );\n};\n","import type { IconProps } from \"../../../types\";\n\nimport React from \"react\";\nimport { getStroke } from \"../../../theme\";\n\nexport const Down = (props: IconProps) => {\n const stroke = getStroke(props);\n return (\n <svg viewBox=\"0 0 24 24\">\n <path\n fill=\"none\"\n stroke={stroke}\n d=\"m16 13-2 2-2 2-2-2-2-2m8-6-2 2-2 2-2-2-2-2\"\n />\n </svg>\n );\n};\n","import type { IconProps } from \"../../../types\";\n\nimport React from \"react\";\nimport { getStroke } from \"../../../theme\";\n\nexport const Eraser = (props: IconProps) => {\n const stroke = getStroke(props);\n return (\n <svg viewBox=\"0 0 24 24\">\n <path\n fill={stroke}\n d=\"m14.333 5.183.165.007c.494.037.978.245 1.356.623l2.333 2.333a2.15 2.15 0 0 1 0 3.04l-5.833 5.834a3.8 3.8 0 0 1-5.374 0l-1.167-1.166a2.15 2.15 0 0 1 0-3.04l7-7c.42-.42.97-.63 1.52-.63ZM11.52 8.52l-4.999 5a1.15 1.15 0 0 0 0 1.626l1.167 1.167a2.8 2.8 0 0 0 3.96 0l3.832-3.833-3.96-3.96Z\"\n />\n </svg>\n );\n};\n","import type { IconProps } from \"../../../types\";\n\nimport React from \"react\";\nimport { getStroke } from \"../../../theme\";\n\nexport const Expand = (props: IconProps) => {\n const stroke = getStroke(props);\n return (\n <svg viewBox=\"0 0 24 24\">\n <path\n fill=\"none\"\n stroke={stroke}\n d=\"m16 10 2 2-2 2M6 6h12M6 18h12M6 14h8m-8-4h8\"\n />\n </svg>\n );\n};\n","import type { IconProps } from \"../../../types\";\n\nimport React from \"react\";\nimport { getStroke } from \"../../../theme\";\n\nexport const Line = (props: IconProps) => {\n const stroke = getStroke(props);\n return (\n <svg viewBox=\"0 0 24 24\">\n <path fill={stroke} d=\"m18.01 5.282.708.708L5.99 18.718l-.708-.708z\" />\n </svg>\n );\n};\n","import type { IconProps } from \"../../../types\";\n\nimport React from \"react\";\nimport { getStroke } from \"../../../theme\";\n\nexport const Pencil = (props: IconProps) => {\n const stroke = getStroke(props);\n return (\n <svg viewBox=\"0 0 24 24\">\n <path\n fill={stroke}\n d=\"m17.497 4.84.116.105 1.442 1.442a1.52 1.52 0 0 1 .104 2.034l-.104.116L8.733 18.858l-4.347.756.756-4.347L15.463 4.945a1.52 1.52 0 0 1 2.034-.104ZM5.967 16.349l-.353 2.037 2.037-.354-1.683-1.683Zm8.407-8.901-7.946 7.946 2.178 2.178 7.946-7.946-2.178-2.178Zm-.728 2.2.708.707-5 5-.708-.708 5-5Zm2.596-4.055-.072.06-1.09 1.088 2.179 2.178 1.089-1.088a.52.52 0 0 0 .105-.584l-.045-.08-.06-.072-1.442-1.442a.52.52 0 0 0-.664-.06Z\"\n />\n </svg>\n );\n};\n","import type { IconProps } from \"../../../types\";\n\nimport React from \"react\";\nimport { getStroke } from \"../../../theme\";\n\nexport const Rectangle = (props: IconProps) => {\n const stroke = getStroke(props);\n return (\n <svg viewBox=\"0 0 24 24\">\n <path fill=\"none\" stroke={stroke} d=\"M5.5 5.5h13v13h-13z\" />\n </svg>\n );\n};\n","import type { IconProps } from \"../../../types\";\n\nimport React from \"react\";\nimport { getStroke } from \"../../../theme\";\n\nexport const Selector = (props: IconProps) => {\n const stroke = getStroke(props);\n return (\n <svg viewBox=\"0 0 24 24\">\n <path\n fill={stroke}\n d=\"m12 12 8 2.667-3.556 1.777L14.667 20 12 12Zm3-8v7.5h-1V5H5v9h6.5v1H4V4h11Z\"\n />\n </svg>\n );\n};\n","import type { IconProps } from \"../../../types\";\n\nimport React from \"react\";\nimport { getStroke } from \"../../../theme\";\n\nexport const SpeechBalloon = (props: IconProps) => {\n const stroke = getStroke(props);\n return (\n <svg viewBox=\"0 0 24 24\">\n <path\n fill=\"none\"\n stroke={stroke}\n d=\"M17 4.5c.414 0 .79.168 1.06.44.272.27.44.646.44 1.06v9c0 .414-.168.79-.44 1.06a1.49 1.49 0 0 1-1.06.44h-4.207l-2.715 2.715-1.81-2.715H7a1.49 1.49 0 0 1-1.06-.44A1.495 1.495 0 0 1 5.5 15V6c0-.414.168-.79.44-1.06A1.49 1.49 0 0 1 7 4.5Z\"\n />\n </svg>\n );\n};\n","import type { IconProps } from \"../../../types\";\n\nimport React from \"react\";\nimport { getStroke } from \"../../../theme\";\n\nexport const Star = (props: IconProps) => {\n const stroke = getStroke(props);\n return (\n <svg viewBox=\"0 0 24 24\">\n <path\n fill=\"none\"\n stroke={stroke}\n d=\"m12 3.523 1.993 5.734 6.07.123-4.838 3.668 1.758 5.81L12 15.391l-4.983 3.467 1.758-5.81L3.938 9.38l6.069-.123L12 3.523Z\"\n />\n </svg>\n );\n};\n","import type { IconProps } from \"../../../types\";\n\nimport React from \"react\";\nimport { getStroke } from \"../../../theme\";\n\nexport const Text = (props: IconProps) => {\n const stroke = getStroke(props);\n return (\n <svg viewBox=\"0 0 24 24\">\n <path\n fill={stroke}\n d=\"M18.5 5.5V8h-1V6.5H13v11h2v1H9v-1h2v-11H6.5V8h-1V5.5h13Z\"\n />\n </svg>\n );\n};\n","import type { IconProps } from \"../../../types\";\n\nimport React from \"react\";\nimport { getStroke } from \"../../../theme\";\n\nexport const Triangle = (props: IconProps) => {\n const stroke = getStroke(props);\n return (\n <svg viewBox=\"0 0 24 24\">\n <path\n fill=\"none\"\n stroke={stroke}\n d=\"M12 6.008 19.138 18.5H4.862L12 6.008Z\"\n />\n </svg>\n );\n};\n","import type { IconProps } from \"../../../types\";\n\nimport React from \"react\";\nimport { getStroke } from \"../../../theme\";\n\nexport const Up = (props: IconProps) => {\n const stroke = getStroke(props);\n return (\n <svg viewBox=\"0 0 24 24\">\n <path\n fill=\"none\"\n stroke={stroke}\n d=\"m16 11-2-2-2-2-2 2-2 2m8 6-2-2-2-2-2 2-2 2\"\n />\n </svg>\n );\n};\n","import { memo } from \"react\";\nimport { Apps } from \"./Apps\";\nimport { Arrow } from \"./Arrow\";\nimport { Circle } from \"./Circle\";\nimport { Clean } from \"./Clean\";\nimport { Clicker } from \"./Clicker\";\nimport { Collapse } from \"./Collapse\";\nimport { Diamond } from \"./Diamond\";\nimport { Down } from \"./Down\";\nimport { Eraser } from \"./Eraser\";\nimport { Expand } from \"./Expand\";\nimport { Line } from \"./Line\";\nimport { Pencil } from \"./Pencil\";\nimport { Rectangle } from \"./Rectangle\";\nimport { Selector } from \"./Selector\";\nimport { SpeechBalloon } from \"./SpeechBalloon\";\nimport { Star } from \"./Star\";\nimport { Text } from \"./Text\";\nimport { Triangle } from \"./Triangle\";\nimport { Up } from \"./Up\";\n\nexport const Icons = {\n Clicker: memo(Clicker),\n Collapse: memo(Collapse),\n Eraser: memo(Eraser),\n Expand: memo(Expand),\n Pencil: memo(Pencil),\n Selector: memo(Selector),\n Rectangle: memo(Rectangle),\n Text: memo(Text),\n Apps: memo(Apps),\n Clean: memo(Clean),\n Circle: memo(Circle),\n Line: memo(Line),\n Arrow: memo(Arrow),\n Star: memo(Star),\n Diamond: memo(Diamond),\n SpeechBalloon: memo(SpeechBalloon),\n Triangle: memo(Triangle),\n Up: memo(Up),\n Down: memo(Down),\n};\n","import type { Placement } from \"tippy.js\";\n\nimport clsx from \"clsx\";\nimport React, { forwardRef, useContext, type PropsWithChildren } from \"react\";\nimport Tippy from \"@tippyjs/react\";\n\nimport { RightOffset } from \"../../../theme\";\nimport { ToolbarContext } from \"../Toolbar\";\n\ntype ButtonProps = PropsWithChildren<{\n content: React.ReactNode;\n disabled?: boolean;\n active?: boolean;\n onClick?: () => void;\n interactive?: boolean;\n placement?: Placement;\n}>;\n\nexport const Button = forwardRef<HTMLButtonElement, ButtonProps>(\n (props, ref) => {\n const {\n content,\n disabled,\n active,\n onClick,\n interactive,\n placement = \"right\",\n children,\n } = props;\n const { writable, theme } = useContext(ToolbarContext);\n\n return (\n <Tippy\n className=\"fastboard-tip\"\n content={content}\n interactive={interactive}\n theme={theme}\n disabled={disabled || !writable}\n placement={placement}\n offset={placement.includes(\"right\") ? RightOffset : undefined}\n duration={300}\n >\n <button\n ref={ref}\n className={clsx(\"fastboard-toolbar-btn\", theme, { active })}\n onClick={onClick}\n disabled={disabled || !writable}\n >\n {children}\n </button>\n </Tippy>\n );\n }\n);\n","import clsx from \"clsx\";\nimport React, { useContext } from \"react\";\nimport { ToolbarContext, name } from \"../Toolbar\";\n\nexport function CutLine() {\n const { theme } = useContext(ToolbarContext);\n return <span className={clsx(`${name}-cut-line`, theme)} />;\n}\n","import type {\n ApplianceNames,\n Color,\n MemberState,\n Room,\n RoomState,\n ShapeType,\n} from \"white-web-sdk\";\n\nimport { useCallback, useEffect, useState } from \"react\";\nimport { noop } from \"../../internal\";\n\nexport function useWritable(room?: Room | null) {\n const [value, setValue] = useState(false);\n\n useEffect(() => {\n if (room) {\n const setWritable = () => setValue(room.isWritable);\n setWritable();\n room.callbacks.on(\"onEnableWriteNowChanged\", setWritable);\n return () => room.callbacks.off(\"onEnableWriteNowChanged\", setWritable);\n }\n }, [room]);\n\n return value;\n}\n\nexport function useRoomState(room?: Room | null) {\n const [memberState, setMemberState] = useState<MemberState | undefined>(\n undefined\n );\n\n useEffect(() => {\n if (room) {\n setMemberState(room.state.memberState);\n const onRoomStateChanged = (diff: Partial<RoomState>) => {\n if (diff.memberState) setMemberState(diff.memberState);\n };\n room.callbacks.on(\"onRoomStateChanged\", onRoomStateChanged);\n return () => room.callbacks.off(\"onRoomStateChanged\", onRoomStateChanged);\n }\n }, [room]);\n\n return { memberState };\n}\n\nexport interface ToolbarHook {\n readonly writable: boolean;\n readonly memberState: MemberState | undefined;\n cleanCurrentScene(): void;\n setAppliance(appliance: ApplianceNames, shape?: ShapeType): void;\n setStrokeWidth(width: number): void;\n setStrokeColor(color: Color): void;\n}\n\nexport function useToolbar(room?: Room | null): ToolbarHook {\n const writable = useWritable(room);\n const { memberState } = useRoomState(room);\n\n const cleanCurrentScene = useCallback(() => {\n if (room?.isWritable) {\n room.cleanCurrentScene();\n }\n }, [room]);\n\n const setAppliance = useCallback(\n (appliance: ApplianceNames, shape?: ShapeType) => {\n if (room?.isWritable) {\n room.setMemberState({\n currentApplianceName: appliance,\n shapeType: shape,\n });\n }\n },\n [room]\n );\n\n const setStrokeWidth = useCallback(\n (strokeWidth: number) => {\n if (room?.isWritable) {\n room.setMemberState({ strokeWidth });\n }\n },\n [room]\n );\n\n const setStrokeColor = useCallback(\n (strokeColor: Color) => {\n if (room?.isWritable) {\n room.setMemberState({ strokeColor });\n }\n },\n [room]\n );\n\n return {\n writable,\n memberState,\n cleanCurrentScene,\n setAppliance,\n setStrokeWidth,\n setStrokeColor,\n };\n}\n\nexport const EmptyToolbarHook: ToolbarHook = {\n writable: false,\n memberState: undefined,\n cleanCurrentScene: noop,\n setAppliance: noop,\n setStrokeWidth: noop,\n setStrokeColor: noop,\n};\n","import { ApplianceNames, ShapeType } from \"white-web-sdk\";\nimport { Icons } from \"./icons\";\n\nexport const ShapesMap = {\n [ApplianceNames.rectangle]: Icons.Rectangle,\n [ApplianceNames.ellipse]: Icons.Circle,\n [ApplianceNames.straight]: Icons.Line,\n [ApplianceNames.arrow]: Icons.Arrow,\n [ShapeType.Pentagram]: Icons.Star,\n [ShapeType.Rhombus]: Icons.Diamond,\n [ShapeType.Triangle]: Icons.Triangle,\n [ShapeType.SpeechBalloon]: Icons.SpeechBalloon,\n} as const;\n\nexport const ApplianceShapes = [\n ApplianceNames.rectangle,\n ApplianceNames.ellipse,\n ApplianceNames.straight,\n ApplianceNames.arrow,\n] as const;\n\nexport const Shapes = [\n ShapeType.Pentagram,\n ShapeType.Rhombus,\n ShapeType.Triangle,\n ShapeType.SpeechBalloon,\n] as const;\n\nexport const ItemHeight = 32 + 4;\nexport const ItemsCount = 8;\nexport const MaxHeight = ItemHeight * ItemsCount - 4;\nexport const MinHeight = ItemHeight * 2 - 4;\n","import React, { useCallback, useContext } from \"react\";\n\nimport { Icon } from \"../../../icons\";\nimport { Icons } from \"../icons\";\nimport { Button } from \"./Button\";\nimport { CutLine } from \"./CutLine\";\nimport { ToolbarContext } from \"../Toolbar\";\nimport { ItemHeight } from \"../const\";\n\nexport interface UpButtonProps {\n disabled: boolean;\n scrollTo: (height: number) => void;\n}\n\nexport function UpButton({ disabled, scrollTo }: UpButtonProps) {\n const { theme, icons } = useContext(ToolbarContext);\n const scrollUp = useCallback(() => scrollTo(-ItemHeight), [scrollTo]);\n\n return (\n <>\n <Button content=\"Up\" disabled={disabled} onClick={scrollUp}>\n <Icon\n fallback={<Icons.Up theme={theme} />}\n src={disabled ? icons?.upIconDisable : icons?.upIcon}\n alt=\"[up]\"\n />\n </Button>\n <CutLine />\n </>\n );\n}\n\nexport function DownButton({ disabled, scrollTo }: UpButtonProps) {\n const { theme, icons } = useContext(ToolbarContext);\n const scrollDown = useCallback(() => scrollTo(ItemHeight), [scrollTo]);\n\n return (\n <>\n <CutLine />\n <Button content=\"Down\" disabled={disabled} onClick={scrollDown}>\n <Icon\n fallback={<Icons.Down theme={theme} />}\n src={disabled ? icons?.downIconDisable : icons?.downIcon}\n alt=\"[down]\"\n />\n </Button>\n </>\n );\n}\n","import type { HotKey } from \"white-web-sdk\";\n\nimport React, { useCallback, useContext } from \"react\";\nimport { ApplianceNames } from \"white-web-sdk\";\n\nimport { defaultHotKeys, useInstance } from \"../../../internal\";\nimport { Icon } from \"../../../icons\";\nimport { Icons } from \"../icons\";\nimport { ToolbarContext } from \"../Toolbar\";\nimport { Button } from \"./Button\";\n\nexport function renderToolTip(text: string | undefined, hotkey?: HotKey) {\n if (!(typeof hotkey === \"string\")) return text;\n return (\n <span className=\"fastboard-toolbar-tooltip\">\n <span>{text}</span>\n <span className=\"fastboard-toolbar-hotkey\">{hotkey.toUpperCase()}</span>\n </span>\n );\n}\n\nexport function ClickerButton() {\n const app = useInstance();\n\n const { theme, icons, writable, setAppliance, memberState, i18n } =\n useContext(ToolbarContext);\n\n const changeAppliance = useCallback(\n () => setAppliance(ApplianceNames.clicker),\n [setAppliance]\n );\n\n const shortcut = app?.config.joinRoom.hotKeys?.changeToClick;\n const appliance = memberState?.currentApplianceName;\n const active = appliance === ApplianceNames.clicker;\n const disabled = !writable;\n\n return (\n <Button\n content={renderToolTip(i18n?.t(\"clicker\"), shortcut)}\n onClick={changeAppliance}\n active={active}\n >\n <Icon\n fallback={<Icons.Clicker theme={theme} active={active} />}\n src={disabled ? icons?.clickerIconDisable : icons?.clickerIcon}\n alt=\"[clicker]\"\n />\n </Button>\n );\n}\n\nexport function SelectorButton() {\n const app = useInstance();\n\n const { theme, icons, writable, setAppliance, memberState, i18n } =\n useContext(ToolbarContext);\n\n const changeAppliance = useCallback(\n () => setAppliance(ApplianceNames.selector),\n [setAppliance]\n );\n\n const appliance = memberState?.currentApplianceName;\n const active = appliance === ApplianceNames.selector;\n const disabled = !writable;\n const shortcut = (app?.config.joinRoom.hotKeys || defaultHotKeys)\n .changeToSelector;\n\n return (\n <Button\n content={renderToolTip(i18n?.t(\"selector\"), shortcut)}\n onClick={changeAppliance}\n active={active}\n >\n <Icon\n fallback={<Icons.Selector theme={theme} active={active} />}\n src={disabled ? icons?.selectorIconDisable : icons?.selectorIcon}\n alt=\"[selector]\"\n />\n </Button>\n );\n}\n\nexport function EraserButton() {\n const app = useInstance();\n\n const { theme, icons, writable, setAppliance, memberState, i18n } =\n useContext(ToolbarContext);\n\n const changeAppliance = useCallback(\n () => setAppliance(ApplianceNames.eraser),\n [setAppliance]\n );\n\n const appliance = memberState?.currentApplianceName;\n const active = appliance === ApplianceNames.eraser;\n const disabled = !writable;\n const shortcut = (app?.config.joinRoom.hotKeys || defaultHotKeys)\n .changeToEraser;\n\n return (\n <Button\n content={renderToolTip(i18n?.t(\"eraser\"), shortcut)}\n onClick={changeAppliance}\n active={active}\n >\n <Icon\n fallback={<Icons.Eraser theme={theme} active={active} />}\n src={disabled ? icons?.eraserIconDisable : icons?.eraserIcon}\n alt=\"[eraser]\"\n />\n </Button>\n );\n}\n\nexport function CleanButton() {\n const { theme, icons, writable, cleanCurrentScene, i18n } =\n useContext(ToolbarContext);\n\n const disabled = !writable;\n\n return (\n <Button content={i18n?.t(\"clean\")} onClick={cleanCurrentScene}>\n <Icon\n fallback={<Icons.Clean theme={theme} />}\n src={disabled ? icons?.cleanIconDisable : icons?.cleanIcon}\n alt=\"[clean]\"\n />\n </Button>\n );\n}\n","export default \"data:image/png;base64,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\"","export default \"data:image/png;base64,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\"","export default \"data:image/png;base64,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\"","import Tippy from \"@tippyjs/react\";\nimport React, { useContext } from \"react\";\n\nimport vscodePNG from \"./assets/vscode.png\";\nimport geogebraPNG from \"./assets/geogebra.png\";\nimport countdownPNG from \"./assets/countdown.png\";\n\nimport { useInstance } from \"../../../internal\";\nimport { Icon } from \"../../../icons\";\nimport { RightOffset } from \"../../../theme\";\nimport { Icons } from \"../icons\";\nimport { ToolbarContext } from \"../Toolbar\";\nimport { Button } from \"./Button\";\n\nexport interface AppsButtonProps {\n content?: React.ReactNode;\n onClick?: () => void;\n}\n\nexport function AppsButton({ content, onClick }: AppsButtonProps) {\n const { theme, icons, writable } = useContext(ToolbarContext);\n\n const disabled = !writable;\n\n const button = (\n <Button content=\"Apps\" onClick={onClick}>\n <Icon\n fallback={<Icons.Apps theme={theme} />}\n src={disabled ? icons?.appsIconDisable : icons?.appsIcon}\n alt=\"[apps]\"\n />\n </Button>\n );\n\n return content === false ? (\n button\n ) : (\n <span className=\"fastboard-toolbar-btn-interactive\">\n <Tippy\n className=\"fastboard-tip\"\n content={renderAppsButtonContent(content)}\n theme={theme}\n placement=\"right-end\"\n trigger=\"click\"\n offset={RightOffset}\n arrow={false}\n interactive\n >\n {button}\n </Tippy>\n </span>\n );\n}\n\nfunction renderAppsButtonContent(content?: React.ReactNode) {\n return (\n <div className=\"fastboard-toolbar-panel apps\">\n <div className=\"fastboard-toolbar-apps\">{content || <DefaultApps />}</div>\n </div>\n );\n}\n\nfunction DefaultApps() {\n const app = useInstance();\n\n return (\n <>\n <AppIcon\n title=\"Code Editor\"\n src={vscodePNG}\n alt=\"[code editor]\"\n onClick={app?.insertCodeEditor.bind(app)}\n />\n <AppIcon\n title=\"GeoGebra\"\n src={geogebraPNG}\n alt=\"[geogebra]\"\n onClick={app?.insertGeoGebra.bind(app)}\n />\n <AppIcon\n title=\"Countdown\"\n src={countdownPNG}\n alt=\"[countdown]\"\n onClick={app?.insertCountdown.bind(app)}\n />\n </>\n );\n}\n\ninterface AppIconProps {\n title: string;\n src: string;\n alt: string;\n onClick?: () => void;\n}\n\nfunction AppIcon({ title, src, alt, onClick }: AppIconProps) {\n return (\n <span className=\"fastboard-toolbar-app-icon\">\n <Button placement=\"top\" content={title} onClick={onClick}>\n <img src={src} alt={alt} title={title} />\n </Button>\n <span className=\"fastboard-toolbar-app-icon-text\">{title}</span>\n </span>\n );\n}\n","import type { Color } from \"white-web-sdk\";\n\nimport clsx from \"clsx\";\nimport React, { useContext } from \"react\";\n\nimport { isEqualArray } from \"../../../internal\";\nimport { ToolbarContext } from \"../Toolbar\";\n\nconst colors: Record<string, Color> = {\n \"#E02020\": [224, 32, 32],\n \"#F7B500\": [247, 181, 0],\n \"#6DD400\": [109, 212, 0],\n \"#32C5FF\": [50, 197, 255],\n \"#0091FF\": [0, 145, 255],\n \"#6236FF\": [98, 54, 255],\n \"#B620E0\": [182, 32, 224],\n \"#6D7278\": [109, 114, 120],\n};\n\nconst colorKeys = Object.keys(colors);\n\nexport function ColorBox() {\n const { theme, memberState, setStrokeColor, writable } =\n useContext(ToolbarContext);\n\n const strokeColor = memberState?.strokeColor;\n const disabled = !writable;\n\n return (\n <div className={clsx(\"fastboard-toolbar-color-box\", theme)}>\n {colorKeys.map((key: string) => (\n <div\n key={key}\n className={clsx(\"fastboard-toolbar-color-item\", theme)}\n onClick={() => setStrokeColor(colors[key])}\n >\n <div\n className={clsx(\"fastboard-toolbar-color-border\", theme, {\n active: strokeColor && isEqualArray(strokeColor, colors[key]),\n })}\n >\n <button\n className={clsx(\"fastboard-toolbar-color-btn\")}\n style={{ background: key }}\n disabled={disabled}\n onClick={ev => {\n ev.stopPropagation();\n setStrokeColor(colors[key]);\n }}\n />\n </div>\n </div>\n ))}\n </div>\n );\n}\n","import clsx from \"clsx\";\nimport RcSlider from \"rc-slider\";\nimport React, { useContext } from \"react\";\n\nimport { themes } from \"../../../theme\";\nimport { ToolbarContext } from \"../Toolbar\";\n\nexport function Slider() {\n const { theme, writable, memberState, setStrokeWidth } =\n useContext(ToolbarContext);\n const { activeColor } = themes[theme];\n\n const strokeWidth = memberState?.strokeWidth || 0;\n\n return (\n <RcSlider\n disabled={!writable}\n className={clsx(\"fastboard-toolbar-slider\", theme)}\n trackStyle={{ background: activeColor }}\n handleStyle={{ border: `1px solid ${activeColor}` }}\n value={strokeWidth}\n onChange={setStrokeWidth}\n min={1}\n max={32}\n />\n );\n}\n","import Tippy from \"@tippyjs/react\";\nimport React, { useCallback } from \"react\";\nimport { useContext } from \"react\";\nimport { ApplianceNames } from \"white-web-sdk\";\n\nimport { defaultHotKeys, useInstance } from \"../../../internal\";\nimport { Icon } from \"../../../icons\";\nimport { RightOffset } from \"../../../theme\";\nimport { Icons } from \"../icons\";\nimport { ToolbarContext } from \"../Toolbar\";\nimport { Button } from \"./Button\";\nimport { ColorBox } from \"./ColorBox\";\nimport { CutLine } from \"./CutLine\";\nimport { Slider } from \"./Slider\";\nimport { renderToolTip } from \"./ApplianceButtons\";\n\nexport function PencilButton() {\n const app = useInstance();\n\n const { theme, icons, writable, setAppliance, memberState, i18n } =\n useContext(ToolbarContext);\n\n const changeAppliance = useCallback(() => {\n setAppliance(ApplianceNames.pencil);\n }, [setAppliance]);\n\n const appliance = memberState?.currentApplianceName;\n const active = appliance === ApplianceNames.pencil;\n const disabled = !writable;\n const shortcut = (app?.config.joinRoom.hotKeys || defaultHotKeys)\n .changeToPencil;\n\n return (\n <span className=\"fastboard-toolbar-btn-interactive\">\n <Tippy\n className=\"fastboard-tip\"\n content={renderPencilButtonContent()}\n theme={theme}\n placement=\"right-start\"\n trigger=\"click\"\n offset={RightOffset}\n arrow={false}\n interactive\n >\n <Button\n content={renderToolTip(i18n?.t(\"pencil\"), shortcut)}\n active={active}\n onClick={changeAppliance}\n >\n <Icon\n fallback={<Icons.Pencil theme={theme} active={active} />}\n src={disabled ? icons?.pencilIconDisable : icons?.pencilIcon}\n alt=\"[pencil]\"\n />\n <span className=\"fastboard-toolbar-triangle\" />\n </Button>\n </Tippy>\n </span>\n );\n}\n\nfunction renderPencilButtonContent() {\n return (\n <div className=\"fastboard-toolbar-panel pencil\">\n <Slider />\n <CutLine />\n <ColorBox />\n </div>\n );\n}\n","import Tippy from \"@tippyjs/react\";\nimport React, { useCallback } from \"react\";\nimport { useContext } from \"react\";\nimport { ApplianceNames } from \"white-web-sdk\";\n\nimport { defaultHotKeys, useInstance } from \"../../../internal\";\nimport { Icon } from \"../../../icons\";\nimport { RightOffset } from \"../../../theme\";\nimport { Icons } from \"../icons\";\nimport { ToolbarContext } from \"../Toolbar\";\nimport { Button } from \"./Button\";\nimport { ColorBox } from \"./ColorBox\";\nimport { renderToolTip } from \"./ApplianceButtons\";\n\nexport function TextButton() {\n const app = useInstance();\n\n const { theme, icons, writable, setAppliance, memberState, i18n } =\n useContext(ToolbarContext);\n\n const changeAppliance = useCallback(() => {\n setAppliance(ApplianceNames.text);\n }, [setAppliance]);\n\n const appliance = memberState?.currentApplianceName;\n const active = appliance === ApplianceNames.text;\n const disabled = !writable;\n const shortcut = (app?.config.joinRoom.hotKeys || defaultHotKeys)\n .changeToText;\n\n return (\n <span className=\"fastboard-toolbar-btn-interactive\">\n <Tippy\n className=\"fastboard-tip\"\n content={renderTextButtonContent()}\n theme={theme}\n placement=\"right-start\"\n trigger=\"click\"\n offset={RightOffset}\n arrow={false}\n interactive\n >\n <Button\n content={renderToolTip(i18n?.t(\"text\"), shortcut)}\n active={active}\n onClick={changeAppliance}\n >\n <Icon\n fallback={<Icons.Text theme={theme} active={active} />}\n src={disabled ? icons?.textIconDisable : icons?.textIcon}\n alt=\"[text]\"\n />\n <span className=\"fastboard-toolbar-triangle\" />\n </Button>\n </Tippy>\n </span>\n );\n}\n\nfunction renderTextButtonContent() {\n return (\n <div className=\"fastboard-toolbar-panel text\">\n <ColorBox />\n </div>\n );\n}\n","import type { IconProps } from \"../../../types\";\n\nimport Tippy from \"@tippyjs/react\";\nimport React, { useContext } from \"react\";\nimport type { ShapeType } from \"white-web-sdk\";\nimport { ApplianceNames } from \"white-web-sdk\";\n\nimport { RightOffset } from \"../../../theme\";\nimport { ApplianceShapes, Shapes, ShapesMap } from \"../const\";\nimport { Icons } from \"../icons\";\nimport { ToolbarContext } from \"../Toolbar\";\nimport { Button } from \"./Button\";\nimport { CutLine } from \"./CutLine\";\nimport { Slider } from \"./Slider\";\nimport { ColorBox } from \"./ColorBox\";\n\nconst ShapeTypes = new Set([...ApplianceShapes, ...Shapes]);\n\nexport function ShapesButton() {\n const { theme, memberState, i18n } = useContext(ToolbarContext);\n\n const appliance = memberState?.currentApplianceName;\n const shape = memberState?.shapeType;\n\n const key = (\n appliance === ApplianceNames.shape ? shape : appliance\n ) as keyof typeof ShapesMap;\n\n const active = ShapeTypes.has(key);\n\n const CurrentIcon = ShapesMap[key] || Icons.Rectangle;\n\n return (\n <span className=\"fastboard-toolbar-btn-interactive\">\n <Tippy\n className=\"fastboard-tip\"\n content={renderShapesButtonContent()}\n theme={theme}\n placement=\"right-start\"\n trigger=\"click\"\n offset={RightOffset}\n arrow={false}\n interactive\n >\n <Button content={i18n?.t(\"shape\")} active={active}>\n <CurrentIcon theme={theme} active={active} />\n <span className=\"fastboard-toolbar-triangle\" />\n </Button>\n </Tippy>\n </span>\n );\n}\n\nfunction renderShapesButtonContent() {\n return (\n <div className=\"fastboard-toolbar-panel shapes\">\n <ShapesBox />\n <CutLine />\n <Slider />\n <CutLine />\n <ColorBox />\n </div>\n );\n}\n\nexport function ShapesBox() {\n const { i18n } = useContext(ToolbarContext);\n return (\n <div className=\"fastboard-toolbar-shapes\">\n {ApplianceShapes.map(Appliance => (\n <ApplianceShapeButton\n key={Appliance}\n content={i18n?.t(Appliance)}\n Appliance={Appliance}\n Icon={ShapesMap[Appliance]}\n />\n ))}\n {Shapes.map(shape => (\n <ShapeShapeButton\n key={shape}\n content={i18n?.t(shape)}\n shape={shape}\n Icon={ShapesMap[shape]}\n />\n ))}\n </div>\n );\n}\n\ninterface ApplianceShapeButtonProps {\n content?: string;\n Appliance: ApplianceNames;\n Icon: React.ComponentType<IconProps>;\n}\n\nfunction ApplianceShapeButton({\n content,\n Appliance,\n Icon,\n}: ApplianceShapeButtonProps) {\n const { theme, writable, setAppliance, memberState } =\n useContext(ToolbarContext);\n\n const current = memberState?.currentApplianceName;\n const disabled = !writable;\n\n return (\n <Button\n content={content}\n disabled={disabled}\n placement=\"top\"\n onClick={() => setAppliance(Appliance)}\n >\n <Icon theme={theme} active={current === Appliance} />\n </Button>\n );\n}\n\ninterface ShapeShapeButtonProps {\n content?: string;\n shape: ShapeType;\n Icon: React.ComponentType<IconProps>;\n}\n\nfunction ShapeShapeButton({ content, shape, Icon }: ShapeShapeButtonProps) {\n const { theme, writable, setAppliance, memberState } =\n useContext(ToolbarContext);\n\n const appliance = memberState?.currentApplianceName;\n const current = appliance === ApplianceNames.shape && memberState?.shapeType;\n const disabled = !writable;\n\n return (\n <Button\n content={content}\n disabled={disabled}\n placement=\"top\"\n onClick={() => setAppliance(ApplianceNames.shape, shape)}\n >\n <Icon theme={theme} active={current === shape} />\n </Button>\n );\n}\n","import React, { useCallback, useEffect, useRef, useState } from \"react\";\n\nimport { useInstance, clamp } from \"../../internal\";\nimport { name } from \"./Toolbar\";\nimport { ItemHeight, ItemsCount, MaxHeight, MinHeight } from \"./const\";\nimport { DownButton, UpButton } from \"./components/UpDownButtons\";\nimport {\n CleanButton,\n ClickerButton,\n EraserButton,\n SelectorButton,\n} from \"./components/ApplianceButtons\";\nimport { AppsButton } from \"./components/AppsButton\";\nimport { PencilButton } from \"./components/PencilButton\";\nimport { TextButton } from \"./components/TextButton\";\nimport { ShapesButton } from \"./components/ShapesButton\";\n\nexport function Content() {\n const app = useInstance();\n const ref = useRef<HTMLDivElement>(null);\n const [scrollTop, setScrollTop] = useState(0);\n const [parentHeight, setParentHeight] = useState(0);\n\n const hasAppButton = app?.config.toolbar?.apps?.enable ?? true;\n const needScroll = parentHeight < ItemHeight * ItemsCount + 48;\n const sectionHeight = clamp(\n parentHeight - 48 * (needScroll ? 3 : 1),\n MinHeight,\n MaxHeight\n );\n const scrollBuffer = Math.max(parentHeight - sectionHeight - 1, 0);\n const disableScrollUp = scrollTop === 0;\n const disableScrollDown = scrollTop === scrollBuffer;\n\n const scrollTo = useCallback(\n (height: number) => {\n setScrollTop(clamp(scrollTop + height, 0, scrollBuffer));\n },\n [scrollBuffer, scrollTop]\n );\n\n useEffect(() => {\n if (ref.current) {\n ref.current.scrollTop = scrollTop;\n }\n }, [scrollTop]);\n\n useEffect(() => {\n const container = ref.current?.parentElement?.parentElement;\n if (container) {\n const { paddingTop, paddingBottom } = getComputedStyle(container);\n const padding = parseInt(paddingTop) + parseInt(paddingBottom) || 0;\n const resizeObserver = new ResizeObserver(() => {\n setParentHeight(container.getBoundingClientRect().height - padding);\n });\n resizeObserver.observe(container);\n return () => resizeObserver.disconnect();\n }\n }, []);\n\n return (\n <>\n {needScroll && (\n <UpButton scrollTo={scrollTo} disabled={disableScrollUp} />\n )}\n <div\n ref={ref}\n className={`${name}-section`}\n style={{\n height: `${sectionHeight}px`,\n overflow: needScroll ? \"hidden\" : \"visible\",\n }}\n >\n <ClickerButton />\n <SelectorButton />\n <PencilButton />\n <TextButton />\n <ShapesButton />\n <EraserButton />\n <CleanButton />\n {hasAppButton && (\n <AppsButton\n content={app?.config.toolbar?.apps?.content}\n onClick={app?.config.toolbar?.apps?.onClick}\n />\n )}\n </div>\n {needScroll && (\n <DownButton scrollTo={scrollTo} disabled={disableScrollDown} />\n )}\n </>\n );\n}\n","import type { CommonProps, GenericIcon, Theme } from \"../../types\";\nimport type { i18n } from \"i18next\";\n\nimport clsx from \"clsx\";\nimport React, { createContext, useCallback, useState } from \"react\";\n\nimport { Icon } from \"../../icons\";\nimport { Icons } from \"./icons\";\nimport { Button } from \"./components/Button\";\nimport { CutLine } from \"./components/CutLine\";\nimport { EmptyToolbarHook, useToolbar, type ToolbarHook } from \"./hooks\";\nimport { Content } from \"./Content\";\n\nexport type ToolbarProps = CommonProps & {\n icons?: GenericIcon<\n | \"clicker\"\n | \"selector\"\n | \"pencil\"\n | \"eraser\"\n | \"clean\"\n | \"expand\"\n | \"collapse\"\n | \"up\"\n | \"down\"\n | \"text\"\n | \"apps\"\n >;\n};\n\ntype ToolbarContextType = ToolbarHook & {\n theme: Theme;\n icons?: ToolbarProps[\"icons\"];\n i18n?: i18n | null;\n};\n\nexport const ToolbarContext = createContext<ToolbarContextType>({\n theme: \"light\",\n ...EmptyToolbarHook,\n});\n\nexport const name = \"fastboard-toolbar\";\n\nexport const Toolbar = ({\n theme = \"light\",\n icons,\n room,\n i18n,\n}: ToolbarProps) => {\n const [expanded, setExpanded] = useState(true);\n const hook = useToolbar(room);\n const toggle = useCallback(() => setExpanded(e => !e), []);\n\n const disabled = !hook.writable;\n\n return (\n <ToolbarContext.Provider value={{ theme, icons, ...hook, i18n }}>\n <div className={clsx(name, theme)}>\n {expanded ? (\n <Button content={i18n?.t(\"collapse\")} onClick={toggle}>\n <Icon\n fallback={<Icons.Collapse theme={theme} />}\n src={disabled ? icons?.collapseIconDisable : icons?.collapseIcon}\n />\n </Button>\n ) : (\n <Button content={i18n?.t(\"expand\")} onClick={toggle}>\n <Icon\n fallback={<Icons.Expand theme={theme} />}\n src={disabled ? icons?.expandIconDisable : icons?.expandIcon}\n />\n </Button>\n )}\n {expanded && (\n <>\n <CutLine />\n <Content />\n </>\n )}\n </div>\n </ToolbarContext.Provider>\n );\n};\n","import type { IconProps } from \"../types\";\n\nimport React from \"react\";\nimport { themes } from \"../theme\";\n\nexport function Undo({ theme = \"light\", active }: IconProps) {\n const config = themes[theme];\n const stroke = active ? config.activeColor : config.color;\n\n return (\n <svg viewBox=\"0 0 24 24\">\n <g\n fill=\"none\"\n fillRule=\"evenodd\"\n stroke={stroke}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"M10 14H6v-4\" />\n <path d=\"m6 14 .788-.9A7.005 7.005 0 0 1 18 14h0\" />\n </g>\n </svg>\n );\n}\n","import type { IconProps } from \"../types\";\n\nimport React from \"react\";\nimport { themes } from \"../theme\";\n\nexport function Redo({ theme = \"light\", active }: IconProps) {\n const config = themes[theme];\n const stroke = active ? config.activeColor : config.color;\n\n return (\n <svg viewBox=\"0 0 24 24\">\n <g\n fill=\"none\"\n fillRule=\"evenodd\"\n stroke={stroke}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"M14 14h4v-4\" />\n <path d=\"m18 14-.788-.9A7.005 7.005 0 0 0 6 14h0\" />\n </g>\n </svg>\n );\n}\n","import type { CommonProps, GenericIcon } from \"../types\";\n\nimport clsx from \"clsx\";\nimport React, { useCallback, useEffect, useState } from \"react\";\nimport Tippy from \"@tippyjs/react\";\n\nimport { Icon } from \"../icons\";\nimport { Undo } from \"../icons/Undo\";\nimport { Redo } from \"../icons/Redo\";\nimport { TopOffset } from \"../theme\";\n\nexport const name = \"fastboard-redo-undo\";\n\nexport type RedoUndoProps = CommonProps & GenericIcon<\"undo\" | \"redo\">;\n\nexport function RedoUndo({\n room,\n theme = \"light\",\n undoIcon,\n undoIconDisable,\n redoIcon,\n redoIconDisable,\n i18n,\n}: RedoUndoProps) {\n const [writable, setWritable] = useState(false);\n const [undoSteps, setUndoSteps] = useState(0);\n const [redoSteps, setRedoSteps] = useState(0);\n\n useEffect(() => {\n if (room) {\n setWritable(room.isWritable);\n room.isWritable && (room.disableSerialization = false);\n\n const updateWritable = () => setWritable(room?.isWritable || false);\n\n room.callbacks.on(\"onEnableWriteNowChanged\", updateWritable);\n room.callbacks.on(\"onCanUndoStepsUpdate\", setUndoSteps);\n room.callbacks.on(\"onCanRedoStepsUpdate\", setRedoSteps);\n return () => {\n room.callbacks.off(\"onEnableWriteNowChanged\", updateWritable);\n room.callbacks.off(\"onCanUndoStepsUpdate\", setUndoSteps);\n room.callbacks.off(\"onCanRedoStepsUpdate\", setRedoSteps);\n };\n }\n }, [room]);\n\n const disabled = !writable;\n\n return (\n <div className={clsx(name, theme)}>\n <Tippy\n className=\"fastboard-tip\"\n content={i18n?.t(\"undo\")}\n theme={theme}\n disabled={disabled}\n placement=\"top\"\n duration={300}\n offset={TopOffset}\n >\n <button\n className={clsx(`${name}-btn`, \"undo\", theme)}\n disabled={disabled || undoSteps === 0}\n onClick={useCallback(() => room && room.undo(), [room])}\n >\n <Icon\n fallback={<Undo theme={theme} />}\n src={undoSteps === 0 ? undoIconDisable : undoIcon}\n alt=\"[undo]\"\n />\n </button>\n </Tippy>\n <Tippy\n className=\"fastboard-tip\"\n content={i18n?.t(\"redo\")}\n theme={theme}\n disabled={disabled}\n placement=\"top\"\n duration={300}\n offset={TopOffset}\n >\n <button\n className={clsx(`${name}-btn`, \"redo\", theme)}\n disabled={disabled || redoSteps === 0}\n onClick={useCallback(() => room && room.redo(), [room])}\n >\n <Icon\n fallback={<Redo theme={theme} />}\n src={redoSteps === 0 ? redoIconDisable : redoIcon}\n alt=\"[redo]\"\n />\n </button>\n </Tippy>\n </div>\n );\n}\n","import type { IconProps } from \"../types\";\n\nimport React from \"react\";\nimport { themes } from \"../theme\";\n\nexport function Minus({ theme = \"light\", active }: IconProps) {\n const config = themes[theme];\n const stroke = active ? config.activeColor : config.color;\n\n return (\n <svg viewBox=\"0 0 24 24\">\n <path\n fill=\"none\"\n stroke={stroke}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"M7 12h10\"\n />\n </svg>\n );\n}\n","import type { IconProps } from \"../types\";\n\nimport React from \"react\";\nimport { themes } from \"../theme\";\n\nexport function Plus({ theme = \"light\", active }: IconProps) {\n const config = themes[theme];\n const stroke = active ? config.activeColor : config.color;\n\n return (\n <svg viewBox=\"0 0 24 24\">\n <path\n fill=\"none\"\n stroke={stroke}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"M12 7v10m-5-5h10\"\n />\n </svg>\n );\n}\n","import type { IconProps } from \"../types\";\n\nimport React from \"react\";\nimport { themes } from \"../theme\";\n\nexport function Reset({ theme = \"light\", active }: IconProps) {\n const config = themes[theme];\n const stroke = active ? config.activeColor : config.color;\n\n return (\n <svg viewBox=\"0 0 24 24\">\n <g fill=\"none\" fillRule=\"evenodd\" transform=\"translate(-176 -684)\">\n <path\n stroke={stroke}\n strokeLinejoin=\"round\"\n d=\"M188 688v4m0 8v4m8-8h-4m-8 0h-4\"\n />\n <circle cx=\"188\" cy=\"696\" r=\"6\" stroke={stroke} />\n <circle cx=\"188\" cy=\"696\" r=\"1\" fill={stroke} />\n </g>\n </svg>\n );\n}\n","import type { RoomState } from \"white-web-sdk\";\nimport type { CommonProps, GenericIcon } from \"../types\";\n\nimport clsx from \"clsx\";\nimport React, { useCallback, useEffect, useState } from \"react\";\nimport Tippy from \"@tippyjs/react\";\n\nimport { clamp } from \"../internal\";\nimport { TopOffset } from \"../theme\";\nimport { Icon } from \"../icons\";\nimport { Minus } from \"../icons/Minus\";\nimport { Plus } from \"../icons/Plus\";\nimport { Reset } from \"../icons/Reset\";\n\nexport const name = \"fastboard-zoom-control\";\n\nexport const ScalePoints: readonly number[] = [\n 0.10737418240000011, 0.13421772800000012, 0.16777216000000014,\n 0.20971520000000016, 0.26214400000000015, 0.3276800000000002,\n 0.4096000000000002, 0.5120000000000001, 0.6400000000000001, 0.8, 1, 1.26,\n 1.5876000000000001, 2.000376, 2.5204737600000002, 3.1757969376000004,\n 4.001504141376, 5.041895218133761, 6.352787974848539, 8.00451284830916, 10,\n];\n\nfunction nextScale(scale: number, delta: 1 | -1) {\n const { length } = ScalePoints;\n const last = length - 1;\n if (scale < ScalePoints[0]) return ScalePoints[0];\n if (scale > ScalePoints[last]) return ScalePoints[last];\n for (let i = 0; i < length; ++i) {\n const curr = ScalePoints[i];\n const prev = i === 0 ? -Infinity : (ScalePoints[i - 1] + curr) / 2;\n const next = i === last ? Infinity : (ScalePoints[i + 1] + curr) / 2;\n if (prev <= scale && scale <= next)\n return ScalePoints[clamp(i + delta, 0, last)];\n }\n return 1;\n}\n\nexport type ZoomControlProps = CommonProps &\n GenericIcon<\"reset\" | \"minus\" | \"plus\">;\n\nexport function ZoomControl({\n room,\n manager,\n theme = \"light\",\n resetIcon,\n resetIconDisable,\n minusIcon,\n minusIconDisable,\n plusIcon,\n plusIconDisable,\n i18n,\n}: ZoomControlProps) {\n const [writable, setWritable] = useState(false);\n const [scale, setScale] = useState(1);\n\n const resetCamera = useCallback(() => {\n if (room?.isWritable) {\n if (manager) {\n manager.mainView.moveCamera({ scale: 1, centerX: 0, centerY: 0 });\n } else {\n const { scenes, index } = room.state.sceneState;\n if (scenes[index].ppt) {\n room.scalePptToFit();\n } else {\n room.moveCamera({ scale: 1, centerX: 0, centerY: 0 });\n }\n }\n }\n }, [room, manager]);\n\n const zoomIn = useCallback(() => {\n if (room?.isWritable) {\n if (manager) {\n manager.mainView.moveCamera({\n scale: nextScale(scale, 1),\n centerX: 0,\n centerY: 0,\n });\n } else {\n room.moveCamera({\n scale: nextScale(scale, 1),\n centerX: 0,\n centerY: 0,\n });\n }\n }\n }, [room, manager, scale]);\n\n const zoomOut = useCallback(() => {\n if (room?.isWritable) {\n if (manager) {\n manager.mainView.moveCamera({\n scale: nextScale(scale, -1),\n centerX: 0,\n centerY: 0,\n });\n } else {\n room.moveCamera({\n scale: nextScale(scale, -1),\n centerX: 0,\n centerY: 0,\n });\n }\n }\n }, [room, manager, scale]);\n\n useEffect(() => {\n if (room) {\n setWritable(room.isWritable);\n setScale(room.state.cameraState.scale);\n }\n\n if (manager) {\n setScale(manager.mainView.camera.scale);\n }\n\n const onRoomStateChanged = (modifyState: Partial<RoomState>) => {\n if (modifyState.cameraState) {\n setScale(modifyState.cameraState.scale);\n }\n };\n\n const onCameraUpdated = ({ scale }: { scale: number }) => setScale(scale);\n\n const updateWritable = () => setWritable(room?.isWritable || false);\n\n if (room) {\n room.callbacks.on(\"onEnableWriteNowChanged\", updateWritable);\n if (manager) {\n manager.mainView.callbacks.on(\"onCameraUpdated\", onCameraUpdated);\n } else {\n room.callbacks.on(\"onRoomStateChanged\", onRoomStateChanged);\n }\n }\n\n return () => {\n if (room) {\n room.callbacks.off(\"onEnableWriteNowChanged\", updateWritable);\n room.callbacks.off(\"onRoomStateChanged\", onRoomStateChanged);\n manager?.mainView.callbacks.off(\"onCameraUpdated\", onCameraUpdated);\n }\n };\n }, [room, manager]);\n\n const disabled = !writable;\n\n return (\n <div className={clsx(name, theme)}>\n {/* <span className={clsx(`${name}-cut-line`, theme)} /> */}\n <Tippy\n className=\"fastboard-tip\"\n content={i18n?.t(\"zoomOut\")}\n theme={theme}\n disabled={disabled}\n placement=\"top\"\n duration={300}\n offset={TopOffset}\n >\n <button\n className={clsx(`${name}-btn`, \"minus\", theme)}\n disabled={disabled}\n onClick={zoomOut}\n >\n <Icon\n fallback={<Minus theme={theme} />}\n src={disabled ? minusIconDisable : minusIcon}\n alt=\"[minus]\"\n />\n </button>\n </Tippy>\n <span className={clsx(`${name}-scale`, theme)}>\n {Math.ceil(scale * 100)}\n </span>\n <span className={clsx(`${name}-percent`, theme)}>%</span>\n <Tippy\n className=\"fastboard-tip\"\n content={i18n?.t(\"zoomIn\")}\n theme={theme}\n disabled={disabled}\n placement=\"top\"\n duration={300}\n offset={TopOffset}\n >\n <button\n className={clsx(`${name}-btn`, \"plus\", theme)}\n disabled={disabled}\n onClick={zoomIn}\n >\n <Icon\n fallback={<Plus theme={theme} />}\n src={disabled ? plusIconDisable : plusIcon}\n alt=\"[plus]\"\n />\n </button>\n </Tippy>\n <Tippy\n className=\"fastboard-tip\"\n content={i18n?.t(\"reset\")}\n theme={theme}\n disabled={disabled}\n placement=\"top\"\n duration={300}\n offset={TopOffset}\n >\n <button\n className={clsx(`${name}-btn`, \"reset\", theme)}\n disabled={disabled}\n onClick={resetCamera}\n >\n <Icon\n fallback={<Reset theme={theme} />}\n src={disabled ? resetIconDisable : resetIcon}\n alt=\"[reset]\"\n />\n </button>\n </Tippy>\n </div>\n );\n}\n","import type { IconProps } from \"../types\";\n\nimport React from \"react\";\nimport { themes } from \"../theme\";\n\nexport function FilePlus({ theme = \"light\", active }: IconProps) {\n const config = themes[theme];\n const stroke = active ? config.activeColor : config.color;\n\n return (\n <svg viewBox=\"0 0 24 24\">\n <path\n fill={stroke}\n d=\"M12 7.5a.5.5 0 0 1 .09.992L12 8.5H8a1.5 1.5 0 0 0-1.493 1.356L6.5 10v6a1.5 1.5 0 0 0 1.356 1.493L8 17.5h6a1.5 1.5 0 0 0 1.493-1.356L15.5 16v-4a.5.5 0 0 1 .992-.09l.008.09v4a2.5 2.5 0 0 1-2.336 2.495L14 18.5H8a2.5 2.5 0 0 1-2.495-2.336L5.5 16v-6a2.5 2.5 0 0 1 2.336-2.495L8 7.5h4Zm4-2a.5.5 0 0 1 .492.41L16.5 6v1.5H18a.5.5 0 0 1 .09.992L18 8.5h-1.5V10a.5.5 0 0 1-.992.09L15.5 10V8.5H14a.5.5 0 0 1-.09-.992L14 7.5h1.5V6a.5.5 0 0 1 .5-.5Z\"\n />\n </svg>\n );\n}\n","import type { IconProps } from \"../types\";\n\nimport React from \"react\";\nimport { themes } from \"../theme\";\n\nexport function ChevronLeft({ theme = \"light\", active }: IconProps) {\n const config = themes[theme];\n const stroke = active ? config.activeColor : config.color;\n\n return (\n <svg viewBox=\"0 0 24 24\">\n <path\n fill=\"none\"\n stroke={stroke}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"m14 16-2-2-2-2 2-2 2-2\"\n />\n </svg>\n );\n}\n","import type { IconProps } from \"../types\";\n\nimport React from \"react\";\nimport { themes } from \"../theme\";\n\nexport function ChevronRight({ theme = \"light\", active }: IconProps) {\n const config = themes[theme];\n const stroke = active ? config.activeColor : config.color;\n\n return (\n <svg viewBox=\"0 0 24 24\">\n <path\n fill=\"none\"\n stroke={stroke}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"m10 16 2-2 2-2-2-2-2-2\"\n />\n </svg>\n );\n}\n","import type { RoomState, ViewVisionMode } from \"white-web-sdk\";\nimport type { CommonProps, GenericIcon } from \"../types\";\n\nimport clsx from \"clsx\";\nimport React, { useCallback, useEffect, useState } from \"react\";\nimport Tippy from \"@tippyjs/react\";\n\nimport { TopOffset } from \"../theme\";\nimport { Icon } from \"../icons\";\nimport { FilePlus } from \"../icons/FilePlus\";\nimport { ChevronLeft } from \"../icons/ChevronLeft\";\nimport { ChevronRight } from \"../icons/ChevronRight\";\n\nexport const name = \"fastboard-page-control\";\n\nexport type PageControlProps = CommonProps &\n GenericIcon<\"add\" | \"prev\" | \"next\">;\n\nexport function PageControl({\n room,\n manager,\n theme = \"light\",\n addIcon,\n addIconDisable,\n prevIcon,\n prevIconDisable,\n nextIcon,\n nextIconDisable,\n i18n,\n}: PageControlProps) {\n const [writable, setWritable] = useState(false);\n const [pageIndex, setPageIndex] = useState(0);\n const [pageCount, setPageCount] = useState(0);\n\n const addPage = useCallback(async () => {\n if (manager && room) {\n await manager.switchMainViewToWriter();\n const path = room.state.sceneState.contextPath;\n room.putScenes(path, [{}], pageIndex + 1);\n await manager.setMainViewSceneIndex(pageIndex + 1);\n } else if (!manager && room) {\n const path = room.state.sceneState.contextPath;\n room.putScenes(path, [{}], pageIndex + 1);\n room.setSceneIndex(pageIndex + 1);\n }\n }, [room, manager, pageIndex]);\n\n const prevPage = useCallback(() => {\n if (room?.isWritable) {\n if (manager) {\n manager.setMainViewSceneIndex(pageIndex - 1);\n } else {\n room.pptPreviousStep();\n }\n }\n }, [room, manager, pageIndex]);\n\n const nextPage = useCallback(() => {\n if (room?.isWritable) {\n if (manager) {\n manager.setMainViewSceneIndex(pageIndex + 1);\n } else {\n room.pptNextStep();\n }\n }\n }, [room, manager, pageIndex]);\n\n useEffect(() => {\n if (room) {\n setWritable(room.isWritable);\n setPageIndex(room.state.sceneState.index);\n setPageCount(room.state.sceneState.scenes.length);\n }\n\n const onRoomStateChanged = (modifyState: Partial<RoomState>) => {\n if (modifyState.sceneState) {\n setPageIndex(modifyState.sceneState.index);\n setPageCount(modifyState.sceneState.scenes.length);\n }\n };\n\n const onMainViewModeChanged = (mode: number) => {\n if (room && mode === (0 as ViewVisionMode.Writable)) {\n setPageIndex(room.state.sceneState.index);\n setPageCount(room.state.sceneState.scenes.length);\n }\n };\n\n const updateWritable = () => setWritable(room?.isWritable || false);\n\n if (room) {\n room.callbacks.on(\"onEnableWriteNowChanged\", updateWritable);\n room.callbacks.on(\"onRoomStateChanged\", onRoomStateChanged);\n manager?.callbacks.on(\"mainViewModeChange\", onMainViewModeChanged);\n }\n\n return () => {\n if (room) {\n room.callbacks.off(\"onEnableWriteNowChanged\", updateWritable);\n room.callbacks.off(\"onRoomStateChanged\", onRoomStateChanged);\n manager?.callbacks.off(\"mainViewModeChange\", onMainViewModeChanged);\n }\n };\n }, [room, manager]);\n\n const disabled = !writable;\n\n return (\n <div className={clsx(name, theme)}>\n {/* <span className={clsx(`${name}-cut-line`, theme)} />{\" \"} */}\n <Tippy\n className=\"fastboard-tip\"\n content={i18n?.t(\"prevPage\")}\n theme={theme}\n disabled={disabled}\n placement=\"top\"\n duration={300}\n offset={TopOffset}\n >\n <button\n className={clsx(`${name}-btn`, \"prev\", theme)}\n disabled={disabled || pageIndex === 0}\n onClick={prevPage}\n >\n <Icon\n fallback={<ChevronLeft theme={theme} />}\n src={disabled ? prevIconDisable : prevIcon}\n alt=\"[prev]\"\n />\n </button>\n </Tippy>\n <span className={clsx(`${name}-page`, theme)}>\n {pageCount === 0 ? \"\\u2026\" : pageIndex + 1}\n </span>\n <span className={clsx(`${name}-slash`, theme)}>/</span>\n <span className={clsx(`${name}-page-count`, theme)}>{pageCount}</span>\n <Tippy\n className=\"fastboard-tip\"\n content={i18n?.t(\"nextPage\")}\n theme={theme}\n disabled={disabled}\n placement=\"top\"\n duration={300}\n offset={TopOffset}\n >\n <button\n className={clsx(`${name}-btn`, \"next\", theme)}\n disabled={disabled || pageIndex === pageCount - 1}\n onClick={nextPage}\n >\n <Icon\n fallback={<ChevronRight theme={theme} />}\n src={disabled ? nextIconDisable : nextIcon}\n alt=\"[next]\"\n />\n </button>\n </Tippy>\n <Tippy\n className=\"fastboard-tip\"\n content={i18n?.t(\"addPage\")}\n theme={theme}\n disabled={disabled}\n placement=\"top\"\n duration={300}\n offset={TopOffset}\n >\n <button\n className={clsx(`${name}-btn`, \"add\", theme)}\n disabled={disabled}\n onClick={addPage}\n >\n <Icon\n fallback={<FilePlus theme={theme} />}\n src={disabled ? addIconDisable : addIcon}\n alt=\"[add]\"\n />\n </button>\n </Tippy>\n </div>\n );\n}\n","import React, { useCallback, useState } from \"react\";\n\nimport { Lock, Instance } from \"../internal\";\nimport { Toolbar } from \"./Toolbar\";\nimport { RedoUndo } from \"./RedoUndo\";\nimport { ZoomControl } from \"./ZoomControl\";\nimport { PageControl } from \"./PageControl\";\n\nexport interface RootProps {\n instance: Instance;\n}\n\nexport function Root({ instance: app }: RootProps) {\n const [mux] = useState(() => new Lock());\n\n const useWhiteboard = useCallback(\n (container: HTMLDivElement | null) =>\n mux.schedule(\n container ? () => app.mount(container) : () => app.unmount()\n ),\n [app, mux]\n );\n\n const {\n Toolbar: toolbar = true,\n RedoUndo: redo_undo = true,\n ZoomControl: zoom_control = true,\n PageControl: page_control = true,\n } = app.config.layout || {};\n\n const props = {\n room: app.room,\n manager: app.manager,\n i18n: app.i18n,\n };\n\n return (\n <Instance.Context.Provider value={app}>\n <div className=\"fastboard-root\">\n {!app.room && <div className=\"fastboard-loading\">Loading&hellip;</div>}\n <div className=\"fastboard-view\" ref={useWhiteboard} />\n {toolbar && (\n <div className=\"fastboard-left\">\n <Toolbar {...props} />\n </div>\n )}\n {(redo_undo || zoom_control) && (\n <div className=\"fastboard-bottom-left\">\n {redo_undo && <RedoUndo {...props} />}\n {zoom_control && <ZoomControl {...props} />}\n </div>\n )}\n {page_control && (\n <div className=\"fastboard-bottom-right\">\n <PageControl {...props} />\n </div>\n )}\n </div>\n </Instance.Context.Provider>\n );\n}\n","import type { Mutable } from \"type-fest\";\nimport type { WindowManager } from \"@netless/window-manager\";\nimport type { Room, SceneDefinition, WhiteWebSdk } from \"white-web-sdk\";\nimport type { JoinRoom, ManagerConfig, SdkConfig } from \"./mount-whiteboard\";\nimport type { i18n } from \"i18next\";\n\nimport React, { createContext, useContext } from \"react\";\nimport ReactDOM from \"react-dom\";\n\nimport { Root } from \"../components/Root\";\nimport { mountWhiteboard } from \"./mount-whiteboard\";\nimport { noop } from \"./helpers\";\n\nexport interface AcceptParams {\n readonly sdk: WhiteWebSdk;\n readonly room: Room;\n readonly manager: WindowManager;\n readonly i18n: i18n;\n}\n\nexport interface InsertDocsStatic {\n readonly fileType: \"pdf\" | \"ppt\";\n readonly scenePath: string;\n readonly scenes: SceneDefinition[];\n readonly title?: string;\n}\n\nexport interface InsertDocsDynamic {\n readonly fileType: \"pptx\";\n readonly scenePath: string;\n readonly taskId: string;\n readonly title?: string;\n readonly url?: string;\n}\n\nexport type InsertDocsParams = InsertDocsStatic | InsertDocsDynamic;\n\nexport type Language = \"zh-CN\" | \"en-US\";\n\nexport interface Layout {\n Toolbar?: boolean;\n PageControl?: boolean;\n RedoUndo?: boolean;\n ZoomControl?: boolean;\n}\n\nexport interface WhiteboardAppConfig {\n readonly sdkConfig: SdkConfig;\n readonly joinRoom: JoinRoom;\n readonly managerConfig?: Omit<ManagerConfig, \"container\">;\n readonly layout?: Layout;\n readonly toolbar?: {\n apps?: {\n enable?: boolean;\n content?: React.ReactNode;\n onClick?: () => void;\n };\n };\n readonly language?: Language;\n}\n\nexport interface Essentials {\n readonly sdk: WhiteWebSdk;\n readonly room: Room;\n readonly manager: WindowManager;\n readonly i18n: i18n;\n}\n\nexport class Instance {\n static readonly Context = createContext<Instance | null>(null);\n\n config: Mutable<WhiteboardAppConfig>;\n\n sdk: WhiteWebSdk | null = null;\n room: Room | null = null;\n manager: WindowManager | null = null;\n i18n: i18n | null = null;\n\n ready = false;\n resolveReady!: () => void;\n readyPromise!: Promise<void>;\n\n refreshReadyPromise() {\n this.readyPromise = new Promise<void>(resolve => {\n this.resolveReady = () => {\n this.resolveReady = noop;\n this.ready = true;\n resolve();\n };\n });\n }\n\n constructor(config: WhiteboardAppConfig) {\n this.config = { ...config };\n this.refreshReadyPromise();\n this.initialize();\n }\n\n async initialize() {\n const essentials = await mountWhiteboard(\n this.config.sdkConfig,\n this.config.joinRoom,\n this.config.managerConfig || {},\n this.config.language || \"en-US\"\n );\n this.accept(essentials);\n this.resolveReady();\n }\n\n target: HTMLElement | null = null;\n collector: HTMLElement | null = null;\n\n bindElement(target: HTMLElement | null, collector: HTMLElement | null) {\n if (this.target && target) {\n ReactDOM.unmountComponentAtNode(this.target);\n }\n this.target = target;\n this.collector = collector;\n this.forceUpdate();\n }\n\n updateLayout(layout: Layout) {\n this.config.layout = layout;\n this.forceUpdate();\n }\n\n async forceUpdate() {\n await this.readyPromise;\n if (this.target) {\n ReactDOM.render(<Root instance={this} />, this.target);\n }\n }\n\n accept({ sdk, room, manager, i18n }: AcceptParams) {\n this.sdk = sdk;\n this.room = room;\n this.manager = manager;\n this.i18n = i18n;\n this.forceUpdate();\n }\n\n async dispose() {\n if (this.room) {\n await this.unmount();\n }\n if (this.target) {\n ReactDOM.unmountComponentAtNode(this.target);\n this.sdk = this.room = this.manager = this.target = null;\n }\n }\n\n async mount(node: HTMLElement) {\n await this.readyPromise;\n if (!this.manager) {\n throw new Error(`[WhiteboardApp] mounted, but not found window manager`);\n }\n if (this.collector) {\n this.manager.bindContainer(node, this.collector);\n } else {\n this.manager.bindContainer(node);\n }\n }\n\n async unmount() {\n if (this.manager) {\n this.manager.destroy();\n this.manager = null;\n }\n if (this.room) {\n try {\n await this.room.disconnect();\n } catch {\n // ignore any error on disconnecting\n }\n this.room = null;\n }\n this.refreshReadyPromise();\n }\n\n insertDocs(params: InsertDocsParams) {\n if (!this.manager) {\n throw new Error(`[WhiteboardApp] cannot insert doc before mounted`);\n }\n switch (params.fileType) {\n case \"pdf\":\n case \"ppt\":\n return this.manager.addApp({\n kind: \"DocsViewer\",\n options: {\n scenePath: params.scenePath,\n title: params.title,\n scenes: params.scenes,\n },\n });\n case \"pptx\":\n return this.manager.addApp({\n kind: \"Slide\",\n options: {\n scenePath: params.scenePath,\n title: params.title,\n },\n attributes: {\n taskId: params.taskId,\n url: params.url,\n },\n });\n }\n }\n\n insertCodeEditor() {\n if (!this.manager) {\n throw new Error(`[WhiteboardApp] cannot insert app before mounted`);\n }\n return this.manager.addApp({\n kind: \"Monaco\",\n options: { title: \"Code Editor\" },\n });\n }\n\n insertGeoGebra() {\n if (!this.manager) {\n throw new Error(`[WhiteboardApp] cannot insert app before mounted`);\n }\n return this.manager.addApp({\n kind: \"GeoGebra\",\n options: { title: \"GeoGebra\" },\n });\n }\n\n insertCountdown() {\n if (!this.manager) {\n throw new Error(`[WhiteboardApp] cannot insert app before mounted`);\n }\n return this.manager.addApp({\n kind: \"Countdown\",\n options: { title: \"Countdown\" },\n });\n }\n\n async changeLanguage(language: Language) {\n try {\n await this.i18n?.changeLanguage(language);\n } finally {\n await this.forceUpdate();\n }\n }\n}\n\nexport function useInstance() {\n return useContext(Instance.Context);\n}\n","import { applyStyles } from \"../internal\";\nimport style from \"../style.scss?inline\";\n\nconst newEl = applyStyles(style);\n\nif (import.meta.hot) {\n import.meta.hot.dispose(data => {\n data.el = newEl;\n });\n import.meta.hot.accept(() => {\n const oldEl = import.meta.hot?.data.el;\n if (oldEl) {\n oldEl.innerText = newEl.innerText;\n newEl.remove();\n }\n });\n}\n","import type {\n InsertDocsParams,\n Language,\n WhiteboardAppConfig,\n} from \"./internal\";\nimport { Instance } from \"./internal\";\n\nexport type { WhiteboardAppConfig, InsertDocsParams };\n\nexport class WhiteboardApp {\n private readonly _instance: Instance;\n\n constructor(readonly config: WhiteboardAppConfig) {\n this._instance = new Instance(config);\n }\n\n get room() {\n return this._instance.room;\n }\n\n get manager() {\n return this._instance.manager;\n }\n\n get sdk() {\n return this._instance.sdk;\n }\n\n get i18n() {\n return this._instance.i18n;\n }\n\n private _target: HTMLElement | null = null;\n public get target(): HTMLElement | null {\n return this._target;\n }\n\n private _collector: HTMLElement | null = null;\n public get collector(): HTMLElement | null {\n return this._collector;\n }\n\n public bindElement(\n target?: HTMLElement | null,\n collector?: HTMLElement | null\n ) {\n this._target = target || null;\n this._collector = collector || null;\n this._instance.bindElement(this._target, this._collector);\n }\n\n public insertDocs(params: InsertDocsParams) {\n return this._instance.insertDocs(params);\n }\n\n public insertCodeEditor() {\n return this._instance.insertCodeEditor();\n }\n\n public insertGeoGebra() {\n return this._instance.insertGeoGebra();\n }\n\n public insertCountdown() {\n return this._instance.insertCountdown();\n }\n\n public changeLanguage(language: Language) {\n return this._instance.changeLanguage(language);\n }\n\n public dispose() {\n return this._instance.dispose();\n }\n}\n","import type { DependencyList } from \"react\";\nimport type { Player } from \"white-web-sdk\";\n\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport { PlayerPhase } from \"white-web-sdk\";\n\nconst EMPTY_ARRAY: DependencyList = [];\n\nfunction useForceUpdate() {\n const [, forceUpdate_] = useState({});\n // eslint-disable-next-line react-hooks/exhaustive-deps\n return useCallback(() => forceUpdate_({}), EMPTY_ARRAY);\n}\n\nfunction useLastValue<T>(value: T) {\n const ref = useRef<T>(value);\n useEffect(() => {\n ref.current = value;\n }, [value]);\n return ref.current;\n}\n\nexport function usePlayer(player?: Player | null) {\n const togglePlay = useCallback(() => {\n if (player) {\n switch (player.phase) {\n case PlayerPhase.WaitingFirstFrame:\n case PlayerPhase.Pause:\n case PlayerPhase.Ended: {\n player.play();\n break;\n }\n case PlayerPhase.Playing: {\n player.pause();\n break;\n }\n }\n }\n }, [player]);\n\n const seekToProgressTime = useCallback(\n (time: number) => {\n if (player) {\n player.seekToProgressTime(time);\n }\n },\n [player]\n );\n\n const lastPlayer = useLastValue(player);\n\n const forceUpdate = useForceUpdate();\n\n const setSpeed = useCallback(\n (speed: number) => {\n if (player) {\n player.playbackSpeed = speed;\n forceUpdate();\n }\n },\n [forceUpdate, player]\n );\n\n useEffect(() => {\n if (!lastPlayer && player) {\n forceUpdate();\n }\n }, [forceUpdate, lastPlayer, player]);\n\n useEffect(() => {\n if (player) {\n player.callbacks.on(\"onPhaseChanged\", forceUpdate);\n player.callbacks.on(\"onProgressTimeChanged\", forceUpdate);\n return () => {\n player.callbacks.off(\"onPhaseChanged\", forceUpdate);\n player.callbacks.off(\"onProgressTimeChanged\", forceUpdate);\n };\n }\n }, [forceUpdate, player]);\n\n const phase = player ? player.phase : PlayerPhase.WaitingFirstFrame;\n const currentTime = player ? player.progressTime : 0;\n const totalTime = player ? player.timeDuration : 0;\n const speed = player ? player.playbackSpeed : 1;\n\n return {\n phase,\n currentTime,\n totalTime,\n speed,\n setSpeed,\n togglePlay,\n seekToProgressTime,\n };\n}\n","import type { IconProps } from \"../../../types\";\n\nimport React from \"react\";\nimport { getStroke } from \"../../../theme\";\n\nexport const Loading = (props: IconProps) => {\n const stroke = getStroke(props);\n return (\n <svg viewBox=\"0 0 24 24\">\n <path d=\"M12 4V2A10 10 0 0 0 2 12h2a8 8 0 0 1 8-8z\" fill={stroke}></path>\n </svg>\n );\n};\n","import type { IconProps } from \"../../../types\";\n\nimport React from \"react\";\nimport { getStroke } from \"../../../theme\";\n\nexport const Pause = (props: IconProps) => {\n const stroke = getStroke(props);\n return (\n <svg viewBox=\"0 0 24 24\">\n <path d=\"M14 19h4V5h-4M6 19h4V5H6v14z\" fill={stroke}></path>\n </svg>\n );\n};\n","import type { IconProps } from \"../../../types\";\n\nimport React from \"react\";\nimport { getStroke } from \"../../../theme\";\n\nexport const Play = (props: IconProps) => {\n const stroke = getStroke(props);\n return (\n <svg viewBox=\"0 0 24 24\">\n <path d=\"M8 5.14v14l11-7l-11-7z\" fill={stroke}></path>\n </svg>\n );\n};\n","import { memo } from \"react\";\nimport { Loading } from \"./Loading\";\nimport { Pause } from \"./Pause\";\nimport { Play } from \"./Play\";\n\nexport const Icons = {\n Play: memo(Play),\n Pause: memo(Pause),\n Loading: memo(Loading),\n};\n","import type { Placement } from \"tippy.js\";\nimport type { Theme } from \"../../../types\";\n\nimport clsx from \"clsx\";\nimport React, { forwardRef, type PropsWithChildren } from \"react\";\nimport Tippy from \"@tippyjs/react\";\n\nimport { TopOffset } from \"../../../theme\";\n\ntype ButtonProps = PropsWithChildren<{\n theme: Theme;\n content: React.ReactNode;\n disabled?: boolean;\n active?: boolean;\n onClick?: () => void;\n interactive?: boolean;\n placement?: Placement;\n}>;\n\nexport const Button = forwardRef<HTMLButtonElement, ButtonProps>(\n (props, ref) => {\n const {\n theme,\n content,\n disabled,\n active,\n onClick,\n interactive,\n placement = \"top\",\n children,\n } = props;\n\n return (\n <Tippy\n className=\"fastboard-tip\"\n content={content}\n interactive={interactive}\n theme={theme}\n disabled={disabled}\n placement={placement}\n offset={TopOffset}\n duration={300}\n >\n <button\n ref={ref}\n className={clsx(\"fastboard-player-control-btn\", theme, { active })}\n onClick={onClick}\n disabled={disabled}\n >\n {children}\n </button>\n </Tippy>\n );\n }\n);\n","import type { Player } from \"white-web-sdk\";\nimport type { CommonProps, GenericIcon } from \"../../types\";\n\nimport clsx from \"clsx\";\nimport React, { useEffect, useState } from \"react\";\nimport RcSlider from \"rc-slider\";\nimport { PlayerPhase } from \"white-web-sdk\";\nimport { usePlayer } from \"./hooks\";\nimport { Icon } from \"../../icons\";\nimport { themes, TopOffset } from \"../../theme\";\nimport { Icons } from \"./icons\";\nimport Tippy from \"@tippyjs/react\";\nimport { Button } from \"./components/Button\";\n\nexport type PlayerControlProps = {\n autoHide?: boolean;\n player?: Player;\n} & Omit<CommonProps, \"room\"> &\n GenericIcon<\"play\" | \"pause\" | \"loading\">;\n\nexport const name = \"fastboard-player-control\";\n\nexport function PlayerControl({\n autoHide = false,\n player: player_,\n theme = \"light\",\n i18n,\n ...icons\n}: PlayerControlProps) {\n const [currentTime, setCurrentTime] = useState(0);\n const player = usePlayer(player_);\n\n useEffect(() => {\n setCurrentTime(player.currentTime);\n }, [player.currentTime]);\n\n useEffect(() => {\n if (player.currentTime !== currentTime) {\n player.seekToProgressTime(currentTime);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [currentTime]);\n\n const isLoading =\n player.phase === PlayerPhase.WaitingFirstFrame ||\n player.phase === PlayerPhase.Buffering;\n const isPlaying = player.phase === PlayerPhase.Playing;\n\n const { activeColor } = themes[theme];\n\n return (\n <div className={clsx(name, theme, { \"auto-hide\": autoHide })}>\n <button\n className={clsx(\n `${name}-btn`,\n isLoading ? \"loading\" : isPlaying ? \"pause\" : \"play\",\n theme\n )}\n disabled={isLoading}\n onClick={player.togglePlay}\n >\n <Icon\n fallback={\n isLoading ? (\n <Icons.Loading theme={theme} />\n ) : isPlaying ? (\n <Icons.Pause theme={theme} />\n ) : (\n <Icons.Play theme={theme} />\n )\n }\n src={\n isLoading\n ? icons.loadingIcon\n : isPlaying\n ? icons.pauseIcon\n : icons.playIcon\n }\n alt={isLoading ? \"[loading]\" : isPlaying ? \"[pause]\" : \"[play]\"}\n />\n </button>\n <span className={clsx(`${name}-slider`, { loading: isLoading }, theme)}>\n <RcSlider\n disabled={isLoading}\n trackStyle={{ background: activeColor }}\n handleStyle={{ border: `1px solid ${activeColor}` }}\n value={currentTime}\n onChange={setCurrentTime}\n min={0}\n max={player.totalTime}\n step={100}\n />\n </span>\n <span className={clsx(`${name}-current`, theme)}>\n {renderTime(player.currentTime)}\n </span>\n <span className={clsx(`${name}-slash`, theme)}>/</span>\n <span className={clsx(`${name}-total`, theme)}>\n {renderTime(player.totalTime)}\n </span>\n <span className={`${name}-btn-interactive`}>\n <Tippy\n className=\"fastboard-tip\"\n content={renderSpeeds(player)}\n theme={theme}\n placement=\"top-end\"\n trigger=\"click\"\n offset={TopOffset}\n arrow={false}\n interactive\n >\n <Button content={i18n?.t(\"speed\")} theme={theme} disabled={isLoading}>\n <span className={clsx(`${name}-speed-text`, theme)}>\n {player.speed}x\n </span>\n </Button>\n </Tippy>\n </span>\n </div>\n );\n}\n\nfunction renderTime(ms: number) {\n let seconds = ms / 1000;\n const minutes = Math.floor(seconds / 60);\n seconds = Math.floor(seconds) % 60;\n\n return (\n `${String(minutes).padStart(2, \"0\")}` +\n `:${String(seconds).padStart(2, \"0\")}`\n );\n}\n\nconst Speeds = [2.0, 1.5, 1.25, 1.0, 0.75, 0.5];\n\nfunction renderSpeeds({\n speed: current,\n setSpeed,\n}: {\n speed: number;\n setSpeed: (speed: number) => void;\n}) {\n return (\n <div className={clsx(`${name}-panel`, \"speed\")}>\n {Speeds.map(speed => (\n <button\n className={clsx(`${name}-btn`, \"speed\", {\n active: speed === current,\n })}\n key={speed}\n onClick={() => setSpeed(speed)}\n >\n {speed}x\n </button>\n ))}\n </div>\n );\n}\n","import type { WhiteboardApp, WhiteboardAppConfig } from \"./WhiteboardApp\";\n\nimport { useEffect, useState } from \"react\";\nimport { createWhiteboardApp } from \"./index\";\n\nexport type FastBoardConfig = WhiteboardAppConfig;\n\n/**\n * @example\n * const [app, ref] = useFastboard({ sdkConfig, joinRoom })\n * if (app) {\n * app.insertDocs({...})\n * }\n * return <div style={{ width: '100%', height: '100%' }} ref={ref} />\n */\nexport function useFastboard(config: FastBoardConfig): readonly [\n app: WhiteboardApp | null,\n ref: (div: HTMLDivElement | null) => void,\n collectorRef: (div: HTMLDivElement | null) => void\n] & {\n readonly app: WhiteboardApp | null;\n readonly ref: (div: HTMLDivElement | null) => void;\n readonly collectorRef: (div: HTMLDivElement | null) => void;\n} {\n const [app, setApp] = useState<WhiteboardApp | null>(null);\n const [currentTarget, ref] = useState<HTMLDivElement | null>(null);\n const [collector, collectorRef] = useState<HTMLDivElement | null>(null);\n\n useEffect(() => {\n let isMounted = true;\n const promise = createWhiteboardApp(config).then(app => {\n if (isMounted) setApp(app);\n });\n return () => {\n isMounted = false;\n promise.then(() => app?.dispose());\n };\n // ignore config and app change\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n useEffect(() => {\n if (app) {\n app.bindElement(currentTarget, collector);\n }\n }, [app, collector, currentTarget]);\n\n return Object.assign([app, ref, collectorRef] as const, {\n app,\n ref,\n collectorRef,\n });\n}\n","import { WindowManager } from \"@netless/window-manager\";\n\nimport \"./behaviors/register-apps\";\nimport \"./behaviors/style\";\n\nimport { WhiteboardApp, type WhiteboardAppConfig } from \"./WhiteboardApp\";\n\nexport { version } from \"../package.json\";\nexport { PageControl, type PageControlProps } from \"./components/PageControl\";\nexport { RedoUndo, type RedoUndoProps } from \"./components/RedoUndo\";\nexport { Toolbar, type ToolbarProps } from \"./components/Toolbar\";\nexport { ZoomControl, type ZoomControlProps } from \"./components/ZoomControl\";\nexport {\n PlayerControl,\n type PlayerControlProps,\n} from \"./components/PlayerControl\";\nexport * from \"./WhiteboardApp\";\nexport * from \"./hooks\";\n\nexport const register = WindowManager.register.bind(WindowManager);\n\n/**\n * @example\n * let app = await createWhiteboardApp(config)\n * app.bindElement(el)\n */\nexport async function createWhiteboardApp(\n config: WhiteboardAppConfig\n): Promise<WhiteboardApp> {\n const app = new WhiteboardApp(config);\n // @ts-expect-error // eslint-disable-line\n await app._instance.readyPromise;\n return app;\n}\n"],"names":["WindowManager","i18next","WhiteWebSdk","DefaultHotKeys","require$$0","jsxRuntimeModule","jsxRuntime.jsx","jsxRuntime.jsxs","jsxRuntime.Fragment","fallback","src","alt","Apps","props","stroke","getStroke","Arrow","Circle","Clean","Clicker","Collapse","Diamond","Down","Eraser","Expand","Line","Pencil","Rectangle","Selector","SpeechBalloon","Star","Text","Triangle","Up","Icons","memo","Button","forwardRef","ref","content","disabled","active","onClick","interactive","placement","children","writable","theme","useContext","ToolbarContext","Tippy","includes","RightOffset","undefined","clsx","name","useState","useCallback","ApplianceNames","ShapeType","scrollTo","icons","scrollUp","ItemHeight","upIconDisable","upIcon","scrollDown","downIconDisable","downIcon","text","hotkey","toUpperCase","app","useInstance","setAppliance","memberState","i18n","changeAppliance","clicker","shortcut","config","joinRoom","hotKeys","changeToClick","appliance","currentApplianceName","renderToolTip","t","clickerIconDisable","clickerIcon","selector","defaultHotKeys","changeToSelector","selectorIconDisable","selectorIcon","eraser","changeToEraser","eraserIconDisable","eraserIcon","cleanCurrentScene","cleanIconDisable","cleanIcon","button","appsIconDisable","appsIcon","renderAppsButtonContent","vscodePNG","insertCodeEditor","bind","geogebraPNG","insertGeoGebra","countdownPNG","insertCountdown","title","colors","colorKeys","Object","keys","setStrokeColor","strokeColor","map","key","isEqualArray","background","ev","stopPropagation","setStrokeWidth","activeColor","themes","strokeWidth","RcSlider","border","pencil","changeToPencil","renderPencilButtonContent","pencilIconDisable","pencilIcon","changeToText","renderTextButtonContent","textIconDisable","textIcon","ShapeTypes","Set","ApplianceShapes","Shapes","shape","shapeType","has","CurrentIcon","ShapesMap","renderShapesButtonContent","Appliance","Icon","current","useRef","scrollTop","setScrollTop","parentHeight","setParentHeight","hasAppButton","toolbar","apps","enable","needScroll","ItemsCount","sectionHeight","clamp","MinHeight","MaxHeight","scrollBuffer","Math","max","disableScrollUp","disableScrollDown","height","container","parentElement","paddingTop","paddingBottom","getComputedStyle","padding","parseInt","resizeObserver","ResizeObserver","getBoundingClientRect","observe","disconnect","overflow","createContext","EmptyToolbarHook","Toolbar","room","expanded","setExpanded","hook","useToolbar","toggle","e","collapseIconDisable","collapseIcon","expandIconDisable","expandIcon","color","undoIcon","undoIconDisable","redoIcon","redoIconDisable","setWritable","undoSteps","setUndoSteps","redoSteps","setRedoSteps","isWritable","disableSerialization","updateWritable","callbacks","on","off","TopOffset","undo","redo","ScalePoints","scale","delta","length","last","i","curr","prev","next","Infinity","manager","resetIcon","resetIconDisable","minusIcon","minusIconDisable","plusIcon","plusIconDisable","setScale","resetCamera","mainView","moveCamera","centerX","centerY","scenes","index","state","sceneState","ppt","scalePptToFit","zoomIn","nextScale","zoomOut","cameraState","camera","onRoomStateChanged","modifyState","onCameraUpdated","ceil","addIcon","addIconDisable","prevIcon","prevIconDisable","nextIcon","nextIconDisable","pageIndex","setPageIndex","pageCount","setPageCount","addPage","switchMainViewToWriter","path","contextPath","putScenes","setMainViewSceneIndex","setSceneIndex","prevPage","pptPreviousStep","nextPage","pptNextStep","onMainViewModeChanged","mode","instance","mux","Lock","useWhiteboard","schedule","mount","unmount","RedoUndo","redo_undo","ZoomControl","zoom_control","PageControl","page_control","layout","constructor","sdk","ready","resolveReady","readyPromise","target","collector","refreshReadyPromise","initialize","Promise","resolve","noop","essentials","mountWhiteboard","sdkConfig","managerConfig","language","accept","bindElement","unmountComponentAtNode","forceUpdate","updateLayout","render","dispose","node","Error","bindContainer","destroy","insertDocs","params","fileType","addApp","kind","options","scenePath","attributes","taskId","url","changeLanguage","Context","Instance","PlayerPhase","Loading","Pause","Play","autoHide","player","player_","currentTime","setCurrentTime","usePlayer","seekToProgressTime","isLoading","phase","WaitingFirstFrame","Buffering","isPlaying","Playing","togglePlay","loadingIcon","pauseIcon","playIcon","loading","totalTime","renderTime","renderSpeeds","speed","ms","seconds","minutes","floor","String","padStart","Speeds","setSpeed"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs.js","sources":["../src/behaviors/register-apps.ts","../src/internal/helpers.ts","../src/i18n/index.ts","../src/internal/mount-whiteboard.ts","../node_modules/.pnpm/object-assign@4.1.1/node_modules/object-assign/index.js","../node_modules/.pnpm/react@17.0.2/node_modules/react/cjs/react-jsx-runtime.production.min.js","../node_modules/.pnpm/react@17.0.2/node_modules/react/jsx-runtime.js","../react/jsx-runtime","../src/icons/index.tsx","../src/theme/index.ts","../src/components/Toolbar/icons/Apps.tsx","../src/components/Toolbar/icons/Arrow.tsx","../src/components/Toolbar/icons/Circle.tsx","../src/components/Toolbar/icons/Clean.tsx","../src/components/Toolbar/icons/Clicker.tsx","../src/components/Toolbar/icons/Collapse.tsx","../src/components/Toolbar/icons/Diamond.tsx","../src/components/Toolbar/icons/Down.tsx","../src/components/Toolbar/icons/Eraser.tsx","../src/components/Toolbar/icons/Expand.tsx","../src/components/Toolbar/icons/Line.tsx","../src/components/Toolbar/icons/Pencil.tsx","../src/components/Toolbar/icons/Rectangle.tsx","../src/components/Toolbar/icons/Selector.tsx","../src/components/Toolbar/icons/SpeechBalloon.tsx","../src/components/Toolbar/icons/Star.tsx","../src/components/Toolbar/icons/Text.tsx","../src/components/Toolbar/icons/Triangle.tsx","../src/components/Toolbar/icons/Up.tsx","../src/components/Toolbar/icons/index.ts","../src/components/Toolbar/components/Button.tsx","../src/components/Toolbar/components/CutLine.tsx","../src/components/Toolbar/hooks.ts","../src/components/Toolbar/const.ts","../src/components/Toolbar/components/UpDownButtons.tsx","../src/components/Toolbar/components/ApplianceButtons.tsx","../src/components/Toolbar/components/assets/vscode.png","../src/components/Toolbar/components/assets/geogebra.png","../src/components/Toolbar/components/assets/countdown.png","../src/components/Toolbar/components/AppsButton.tsx","../src/components/Toolbar/components/ColorBox.tsx","../src/components/Toolbar/components/Slider.tsx","../src/components/Toolbar/components/PencilButton.tsx","../src/components/Toolbar/components/TextButton.tsx","../src/components/Toolbar/components/ShapesButton.tsx","../src/components/Toolbar/Content.tsx","../src/components/Toolbar/Toolbar.tsx","../src/icons/Undo.tsx","../src/icons/Redo.tsx","../src/components/RedoUndo.tsx","../src/icons/Minus.tsx","../src/icons/Plus.tsx","../src/icons/Reset.tsx","../src/components/ZoomControl.tsx","../src/icons/FilePlus.tsx","../src/icons/ChevronLeft.tsx","../src/icons/ChevronRight.tsx","../src/components/PageControl.tsx","../src/components/Root.tsx","../src/internal/Instance.tsx","../src/behaviors/style.ts","../src/WhiteboardApp.ts","../src/components/PlayerControl/hooks.ts","../src/components/PlayerControl/icons/Loading.tsx","../src/components/PlayerControl/icons/Pause.tsx","../src/components/PlayerControl/icons/Play.tsx","../src/components/PlayerControl/icons/index.ts","../src/components/PlayerControl/components/Button.tsx","../src/components/PlayerControl/PlayerControl.tsx","../src/hooks.ts","../src/index.ts"],"sourcesContent":["import { WindowManager } from \"@netless/window-manager\";\n\nWindowManager.register({\n kind: \"Slide\",\n appOptions: {\n // turn on to show debug controller\n debug: false,\n },\n src: async () => {\n const app = await import(\"@netless/app-slide\");\n return app.default ?? app;\n },\n});\n\nWindowManager.register({\n kind: \"Monaco\",\n src: async () => {\n const app = await import(\"@netless/app-monaco\");\n return app.default ?? app;\n },\n});\nWindowManager.register({\n kind: \"Countdown\",\n src: async () => {\n const app = await import(\"@netless/app-countdown\");\n return app.default ?? app;\n },\n});\nWindowManager.register({\n kind: \"GeoGebra\",\n src: async () => {\n const app = await import(\"@netless/app-geogebra\");\n return app.default ?? app;\n },\n appOptions: {\n HTML5Codebase:\n \"https://flat-storage-cn-hz.whiteboard.agora.io/GeoGebra/HTML5/5.0/web3d\",\n },\n});\n","export function noop() {\n return;\n}\n\nexport function applyStyles(css: string) {\n const el = document.createElement(\"style\");\n el.appendChild(document.createTextNode(css));\n document.head.appendChild(el);\n return el;\n}\n\nexport function clamp(value: number, min: number, max: number) {\n return value < min ? min : value > max ? max : value;\n}\n\nexport function isEqualArray<T>(a: T[], b: T[]) {\n return a.length === b.length && a.every((e, i) => e === b[i]);\n}\n\nexport type TaskFn = () => Promise<void> | void;\n\nexport class Lock {\n running = false;\n private nextFn: TaskFn | null = null;\n schedule(fn: TaskFn) {\n if (this.running) {\n this.nextFn = fn;\n } else {\n this.running = true;\n Promise.resolve(fn()).then(this.step);\n }\n }\n private step = () => {\n if (this.nextFn) {\n const fn = this.nextFn;\n this.nextFn = null;\n Promise.resolve(fn()).then(this.step);\n } else {\n this.running = false;\n }\n };\n}\n","import i18next from \"i18next\";\nimport en from \"./en.json\";\nimport zhCN from \"./zh-CN.json\";\n\nexport type CreateI18nParams = {\n language?: string;\n};\n\nexport const createI18n = async (params: CreateI18nParams) => {\n const defaultLang = navigator.language || \"zh-CN\";\n const lng = params.language || defaultLang;\n\n await i18next.init({\n lng,\n resources: {\n en: en,\n \"zh-CN\": zhCN,\n },\n });\n\n return i18next;\n};\n","import type { MountParams } from \"@netless/window-manager\";\nimport type {\n JoinRoomParams,\n RoomCallbacks,\n WhiteWebSdkConfiguration,\n} from \"white-web-sdk\";\nimport type { Essentials, Language } from \"./Instance\";\n\nimport { WindowManager } from \"@netless/window-manager\";\nimport { DefaultHotKeys, WhiteWebSdk } from \"white-web-sdk\";\nimport { createI18n } from \"../i18n\";\n\nexport type SdkConfig = Omit<\n WhiteWebSdkConfiguration,\n \"useMobXState\" | \"disableNewPencil\" | \"disableMagixEventDispatchLimit\"\n>;\nexport type JoinRoom = Omit<\n JoinRoomParams,\n \"useMultiViews\" | \"disableMagixEventDispatchLimit\"\n> & { callbacks?: Partial<RoomCallbacks> };\nexport type ManagerConfig = Omit<MountParams, \"room\">;\n\nfunction ensureWindowManager(joinRoom: JoinRoom) {\n if (\n !joinRoom.invisiblePlugins ||\n !joinRoom.invisiblePlugins.includes(WindowManager)\n ) {\n joinRoom.invisiblePlugins = [\n ...(joinRoom.invisiblePlugins || []),\n WindowManager,\n ];\n }\n}\n\nexport const defaultHotKeys = {\n changeToSelector: \"s\",\n changeToLaserPointer: \"z\",\n changeToPencil: \"p\",\n changeToRectangle: \"r\",\n changeToEllipse: \"c\",\n changeToEraser: \"e\",\n changeToText: \"t\",\n changeToStraight: \"l\",\n changeToArrow: \"a\",\n changeToHand: \"h\",\n};\n\nexport async function mountWhiteboard(\n sdkConfig: SdkConfig,\n joinRoom: JoinRoom,\n managerConfig: ManagerConfig,\n language: Language\n): Promise<Essentials> {\n const sdk = new WhiteWebSdk({\n ...sdkConfig,\n useMobXState: true,\n });\n\n ensureWindowManager(joinRoom);\n joinRoom = { ...joinRoom };\n const callbacks = joinRoom.callbacks;\n delete joinRoom.callbacks;\n const joinRoomParams: JoinRoomParams = {\n floatBar: true,\n hotKeys: {\n ...DefaultHotKeys,\n ...defaultHotKeys,\n },\n ...joinRoom,\n useMultiViews: true,\n disableNewPencil: false,\n disableMagixEventDispatchLimit: true,\n };\n const room = await sdk.joinRoom(joinRoomParams, callbacks);\n\n const manager = await WindowManager.mount({\n cursor: true,\n debug: import.meta.env.DEV,\n ...managerConfig,\n room,\n });\n\n const i18n = await createI18n({ language });\n\n if (import.meta.env.DEV) {\n Object.assign(window, { sdk, room, manager });\n }\n\n return { sdk, room, manager, i18n };\n}\n","/*\nobject-assign\n(c) Sindre Sorhus\n@license MIT\n*/\n\n'use strict';\n/* eslint-disable no-unused-vars */\nvar getOwnPropertySymbols = Object.getOwnPropertySymbols;\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\nvar propIsEnumerable = Object.prototype.propertyIsEnumerable;\n\nfunction toObject(val) {\n\tif (val === null || val === undefined) {\n\t\tthrow new TypeError('Object.assign cannot be called with null or undefined');\n\t}\n\n\treturn Object(val);\n}\n\nfunction shouldUseNative() {\n\ttry {\n\t\tif (!Object.assign) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// Detect buggy property enumeration order in older V8 versions.\n\n\t\t// https://bugs.chromium.org/p/v8/issues/detail?id=4118\n\t\tvar test1 = new String('abc'); // eslint-disable-line no-new-wrappers\n\t\ttest1[5] = 'de';\n\t\tif (Object.getOwnPropertyNames(test1)[0] === '5') {\n\t\t\treturn false;\n\t\t}\n\n\t\t// https://bugs.chromium.org/p/v8/issues/detail?id=3056\n\t\tvar test2 = {};\n\t\tfor (var i = 0; i < 10; i++) {\n\t\t\ttest2['_' + String.fromCharCode(i)] = i;\n\t\t}\n\t\tvar order2 = Object.getOwnPropertyNames(test2).map(function (n) {\n\t\t\treturn test2[n];\n\t\t});\n\t\tif (order2.join('') !== '0123456789') {\n\t\t\treturn false;\n\t\t}\n\n\t\t// https://bugs.chromium.org/p/v8/issues/detail?id=3056\n\t\tvar test3 = {};\n\t\t'abcdefghijklmnopqrst'.split('').forEach(function (letter) {\n\t\t\ttest3[letter] = letter;\n\t\t});\n\t\tif (Object.keys(Object.assign({}, test3)).join('') !==\n\t\t\t\t'abcdefghijklmnopqrst') {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn true;\n\t} catch (err) {\n\t\t// We don't expect any of the above to throw, but better to be safe.\n\t\treturn false;\n\t}\n}\n\nmodule.exports = shouldUseNative() ? Object.assign : function (target, source) {\n\tvar from;\n\tvar to = toObject(target);\n\tvar symbols;\n\n\tfor (var s = 1; s < arguments.length; s++) {\n\t\tfrom = Object(arguments[s]);\n\n\t\tfor (var key in from) {\n\t\t\tif (hasOwnProperty.call(from, key)) {\n\t\t\t\tto[key] = from[key];\n\t\t\t}\n\t\t}\n\n\t\tif (getOwnPropertySymbols) {\n\t\t\tsymbols = getOwnPropertySymbols(from);\n\t\t\tfor (var i = 0; i < symbols.length; i++) {\n\t\t\t\tif (propIsEnumerable.call(from, symbols[i])) {\n\t\t\t\t\tto[symbols[i]] = from[symbols[i]];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn to;\n};\n","/** @license React v17.0.2\n * react-jsx-runtime.production.min.js\n *\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n'use strict';require(\"object-assign\");var f=require(\"react\"),g=60103;exports.Fragment=60107;if(\"function\"===typeof Symbol&&Symbol.for){var h=Symbol.for;g=h(\"react.element\");exports.Fragment=h(\"react.fragment\")}var m=f.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentOwner,n=Object.prototype.hasOwnProperty,p={key:!0,ref:!0,__self:!0,__source:!0};\nfunction q(c,a,k){var b,d={},e=null,l=null;void 0!==k&&(e=\"\"+k);void 0!==a.key&&(e=\"\"+a.key);void 0!==a.ref&&(l=a.ref);for(b in a)n.call(a,b)&&!p.hasOwnProperty(b)&&(d[b]=a[b]);if(c&&c.defaultProps)for(b in a=c.defaultProps,a)void 0===d[b]&&(d[b]=a[b]);return{$$typeof:g,type:c,key:e,ref:l,props:d,_owner:m.current}}exports.jsx=q;exports.jsxs=q;\n","'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n module.exports = require('./cjs/react-jsx-runtime.production.min.js');\n} else {\n module.exports = require('./cjs/react-jsx-runtime.development.js');\n}\n","import * as jsxRuntime from \"/home/runner/work/fastboard/fastboard/node_modules/react/jsx-runtime.js\"\nexport const jsx = jsxRuntime.jsx\nexport const jsxs = jsxRuntime.jsxs\nexport const Fragment = jsxRuntime.Fragment","import React from \"react\";\n\nexport interface IconPropsWithFallback {\n fallback: React.ReactElement;\n src?: string;\n alt?: string;\n}\n\nexport function Icon({ fallback, src, alt = \"[icon]\" }: IconPropsWithFallback) {\n return src ? <img src={src} alt={alt} title={alt} /> : fallback;\n}\n","import type { IconProps } from \"../types\";\n\nexport interface ThemeConfig {\n color: string;\n activeColor: string;\n backgroundColor: string;\n hoverBackgroundColor: string;\n}\n\nexport const light: ThemeConfig = {\n color: \"#5D5D5D\",\n activeColor: \"#3381FF\",\n backgroundColor: \"#fff\",\n hoverBackgroundColor: \"rgba(51, 129, 255, 0.1)\",\n};\n\nexport const dark: ThemeConfig = {\n ...light,\n color: \"#eee\",\n backgroundColor: \"#111\",\n};\n\nexport const themes = { light, dark };\n\nexport const getStroke = (props: IconProps) => {\n let config;\n if (props.theme) {\n config = themes[props.theme];\n } else {\n config = themes.light;\n }\n return props.active ? config.activeColor : config.color;\n};\n\nexport const TopOffset = [0, 11] as [number, number];\nexport const RightOffset = [0, 11] as [number, number];\n","import type { IconProps } from \"../../../types\";\n\nimport React from \"react\";\nimport { getStroke } from \"../../../theme\";\n\nexport const Apps = (props: IconProps) => {\n const stroke = getStroke(props);\n return (\n <svg viewBox=\"0 0 24 24\">\n <g fill={stroke}>\n <path d=\"M17.667 4.5h-3.334c-1.012 0-1.833.82-1.833 1.833V11.5h5.167c1.012 0 1.833-.82 1.833-1.833V6.333c0-1.012-.82-1.833-1.833-1.833Zm-3.334 1h3.334c.46 0 .833.373.833.833v3.334l-.006.104a.833.833 0 0 1-.827.729H13.5V6.333c0-.46.373-.833.833-.833Z\" />\n <path d=\"M6.333 19.5A1.833 1.833 0 0 1 4.5 17.667v-3.334c0-.525.221-1 .576-1.334a1.822 1.822 0 0 1-.576-1.332V8.333c0-1.012.82-1.833 1.833-1.833H10A1.5 1.5 0 0 1 11.5 8v4.5h4.167c.962 0 1.75.74 1.827 1.683l.006.15v3.334c0 1.012-.82 1.833-1.833 1.833Zm4.167-6H6.333a.833.833 0 0 0-.827.729l-.006.104v3.334c0 .46.373.833.833.833H10.5v-5Zm5.167 0H11.5v5h4.167c.46 0 .833-.373.833-.833v-3.334a.833.833 0 0 0-.833-.833ZM10 7.5H6.333a.833.833 0 0 0-.833.833v3.334c0 .46.373.833.833.833H10.5V8a.5.5 0 0 0-.41-.492L10 7.5Z\" />\n </g>\n </svg>\n );\n};\n","import type { IconProps } from \"../../../types\";\n\nimport React from \"react\";\nimport { getStroke } from \"../../../theme\";\n\nexport const Arrow = (props: IconProps) => {\n const stroke = getStroke(props);\n return (\n <svg viewBox=\"0 0 24 24\">\n <path\n fill={stroke}\n d=\"M19 5v6l-2.647-2.646L5.99 18.718l-.708-.708L15.645 7.646 13 5h6Z\"\n />\n </svg>\n );\n};\n","import type { IconProps } from \"../../../types\";\n\nimport React from \"react\";\nimport { getStroke } from \"../../../theme\";\n\nexport const Circle = (props: IconProps) => {\n const stroke = getStroke(props);\n return (\n <svg viewBox=\"0 0 24 24\">\n <rect\n width=\"15\"\n height=\"15\"\n x=\"4.5\"\n y=\"4.5\"\n fill=\"none\"\n stroke={stroke}\n rx=\"7.5\"\n />\n </svg>\n );\n};\n","import type { IconProps } from \"../../../types\";\n\nimport React from \"react\";\nimport { getStroke } from \"../../../theme\";\n\nexport const Clean = (props: IconProps) => {\n const stroke = getStroke(props);\n return (\n <svg viewBox=\"0 0 24 24\">\n <path\n fill={stroke}\n d=\"M9.754 11.99c0 1.856-.711 3.62-1.96 4.951l-.151.155h1.403l.855-.853h.707l.853.853h2.635l.094-.064a6.237 6.237 0 0 0 2.559-4.781l.005-.26h1a7.237 7.237 0 0 1-2.994 5.862l-.229.16-.277.083h-3l-.353-.146-.647-.647-.646.647-.354.146h-3l-.286-.91.214-.148a6.237 6.237 0 0 0 2.567-4.787l.005-.26h1Zm4.772-6.502v2l.35.039a2.98 2.98 0 0 1 2.644 2.78l.006.181h-8a2.98 2.98 0 0 1 2.65-2.961l.35-.039v-2h2Z\"\n />\n </svg>\n );\n};\n","import type { IconProps } from \"../../../types\";\n\nimport React from \"react\";\nimport { getStroke } from \"../../../theme\";\n\nexport const Clicker = (props: IconProps) => {\n const stroke = getStroke(props);\n return (\n <svg viewBox=\"0 0 24 24\">\n <g fill=\"none\">\n <path d=\"M0 0h24v24H0z\" />\n <path\n fill={stroke}\n d=\"m7 5.072 10.33 7.892-4.879.549 3.232 5.598-.866.5-3.233-5.597-2.914 3.95L7 5.072Z\"\n />\n </g>\n </svg>\n );\n};\n","import type { IconProps } from \"../../../types\";\n\nimport React from \"react\";\nimport { getStroke } from \"../../../theme\";\n\nexport const Collapse = (props: IconProps) => {\n const stroke = getStroke(props);\n return (\n <svg viewBox=\"0 0 24 24\">\n <path\n fill=\"none\"\n stroke={stroke}\n d=\"m8 10-2 2 2 2m10-8H6m12 12H6m12-4h-8m8-4h-8\"\n />\n </svg>\n );\n};\n","import type { IconProps } from \"../../../types\";\n\nimport React from \"react\";\nimport { getStroke } from \"../../../theme\";\n\nexport const Diamond = (props: IconProps) => {\n const stroke = getStroke(props);\n return (\n <svg viewBox=\"0 0 24 24\">\n <path\n fill=\"none\"\n stroke={stroke}\n d=\"M4.222 12 12 4.222 19.778 12 12 19.778z\"\n />\n </svg>\n );\n};\n","import type { IconProps } from \"../../../types\";\n\nimport React from \"react\";\nimport { getStroke } from \"../../../theme\";\n\nexport const Down = (props: IconProps) => {\n const stroke = getStroke(props);\n return (\n <svg viewBox=\"0 0 24 24\">\n <path\n fill=\"none\"\n stroke={stroke}\n d=\"m16 13-2 2-2 2-2-2-2-2m8-6-2 2-2 2-2-2-2-2\"\n />\n </svg>\n );\n};\n","import type { IconProps } from \"../../../types\";\n\nimport React from \"react\";\nimport { getStroke } from \"../../../theme\";\n\nexport const Eraser = (props: IconProps) => {\n const stroke = getStroke(props);\n return (\n <svg viewBox=\"0 0 24 24\">\n <path\n fill={stroke}\n d=\"m14.333 5.183.165.007c.494.037.978.245 1.356.623l2.333 2.333a2.15 2.15 0 0 1 0 3.04l-5.833 5.834a3.8 3.8 0 0 1-5.374 0l-1.167-1.166a2.15 2.15 0 0 1 0-3.04l7-7c.42-.42.97-.63 1.52-.63ZM11.52 8.52l-4.999 5a1.15 1.15 0 0 0 0 1.626l1.167 1.167a2.8 2.8 0 0 0 3.96 0l3.832-3.833-3.96-3.96Z\"\n />\n </svg>\n );\n};\n","import type { IconProps } from \"../../../types\";\n\nimport React from \"react\";\nimport { getStroke } from \"../../../theme\";\n\nexport const Expand = (props: IconProps) => {\n const stroke = getStroke(props);\n return (\n <svg viewBox=\"0 0 24 24\">\n <path\n fill=\"none\"\n stroke={stroke}\n d=\"m16 10 2 2-2 2M6 6h12M6 18h12M6 14h8m-8-4h8\"\n />\n </svg>\n );\n};\n","import type { IconProps } from \"../../../types\";\n\nimport React from \"react\";\nimport { getStroke } from \"../../../theme\";\n\nexport const Line = (props: IconProps) => {\n const stroke = getStroke(props);\n return (\n <svg viewBox=\"0 0 24 24\">\n <path fill={stroke} d=\"m18.01 5.282.708.708L5.99 18.718l-.708-.708z\" />\n </svg>\n );\n};\n","import type { IconProps } from \"../../../types\";\n\nimport React from \"react\";\nimport { getStroke } from \"../../../theme\";\n\nexport const Pencil = (props: IconProps) => {\n const stroke = getStroke(props);\n return (\n <svg viewBox=\"0 0 24 24\">\n <path\n fill={stroke}\n d=\"m17.497 4.84.116.105 1.442 1.442a1.52 1.52 0 0 1 .104 2.034l-.104.116L8.733 18.858l-4.347.756.756-4.347L15.463 4.945a1.52 1.52 0 0 1 2.034-.104ZM5.967 16.349l-.353 2.037 2.037-.354-1.683-1.683Zm8.407-8.901-7.946 7.946 2.178 2.178 7.946-7.946-2.178-2.178Zm-.728 2.2.708.707-5 5-.708-.708 5-5Zm2.596-4.055-.072.06-1.09 1.088 2.179 2.178 1.089-1.088a.52.52 0 0 0 .105-.584l-.045-.08-.06-.072-1.442-1.442a.52.52 0 0 0-.664-.06Z\"\n />\n </svg>\n );\n};\n","import type { IconProps } from \"../../../types\";\n\nimport React from \"react\";\nimport { getStroke } from \"../../../theme\";\n\nexport const Rectangle = (props: IconProps) => {\n const stroke = getStroke(props);\n return (\n <svg viewBox=\"0 0 24 24\">\n <path fill=\"none\" stroke={stroke} d=\"M5.5 5.5h13v13h-13z\" />\n </svg>\n );\n};\n","import type { IconProps } from \"../../../types\";\n\nimport React from \"react\";\nimport { getStroke } from \"../../../theme\";\n\nexport const Selector = (props: IconProps) => {\n const stroke = getStroke(props);\n return (\n <svg viewBox=\"0 0 24 24\">\n <path\n fill={stroke}\n d=\"m12 12 8 2.667-3.556 1.777L14.667 20 12 12Zm3-8v7.5h-1V5H5v9h6.5v1H4V4h11Z\"\n />\n </svg>\n );\n};\n","import type { IconProps } from \"../../../types\";\n\nimport React from \"react\";\nimport { getStroke } from \"../../../theme\";\n\nexport const SpeechBalloon = (props: IconProps) => {\n const stroke = getStroke(props);\n return (\n <svg viewBox=\"0 0 24 24\">\n <path\n fill=\"none\"\n stroke={stroke}\n d=\"M17 4.5c.414 0 .79.168 1.06.44.272.27.44.646.44 1.06v9c0 .414-.168.79-.44 1.06a1.49 1.49 0 0 1-1.06.44h-4.207l-2.715 2.715-1.81-2.715H7a1.49 1.49 0 0 1-1.06-.44A1.495 1.495 0 0 1 5.5 15V6c0-.414.168-.79.44-1.06A1.49 1.49 0 0 1 7 4.5Z\"\n />\n </svg>\n );\n};\n","import type { IconProps } from \"../../../types\";\n\nimport React from \"react\";\nimport { getStroke } from \"../../../theme\";\n\nexport const Star = (props: IconProps) => {\n const stroke = getStroke(props);\n return (\n <svg viewBox=\"0 0 24 24\">\n <path\n fill=\"none\"\n stroke={stroke}\n d=\"m12 3.523 1.993 5.734 6.07.123-4.838 3.668 1.758 5.81L12 15.391l-4.983 3.467 1.758-5.81L3.938 9.38l6.069-.123L12 3.523Z\"\n />\n </svg>\n );\n};\n","import type { IconProps } from \"../../../types\";\n\nimport React from \"react\";\nimport { getStroke } from \"../../../theme\";\n\nexport const Text = (props: IconProps) => {\n const stroke = getStroke(props);\n return (\n <svg viewBox=\"0 0 24 24\">\n <path\n fill={stroke}\n d=\"M18.5 5.5V8h-1V6.5H13v11h2v1H9v-1h2v-11H6.5V8h-1V5.5h13Z\"\n />\n </svg>\n );\n};\n","import type { IconProps } from \"../../../types\";\n\nimport React from \"react\";\nimport { getStroke } from \"../../../theme\";\n\nexport const Triangle = (props: IconProps) => {\n const stroke = getStroke(props);\n return (\n <svg viewBox=\"0 0 24 24\">\n <path\n fill=\"none\"\n stroke={stroke}\n d=\"M12 6.008 19.138 18.5H4.862L12 6.008Z\"\n />\n </svg>\n );\n};\n","import type { IconProps } from \"../../../types\";\n\nimport React from \"react\";\nimport { getStroke } from \"../../../theme\";\n\nexport const Up = (props: IconProps) => {\n const stroke = getStroke(props);\n return (\n <svg viewBox=\"0 0 24 24\">\n <path\n fill=\"none\"\n stroke={stroke}\n d=\"m16 11-2-2-2-2-2 2-2 2m8 6-2-2-2-2-2 2-2 2\"\n />\n </svg>\n );\n};\n","import { memo } from \"react\";\nimport { Apps } from \"./Apps\";\nimport { Arrow } from \"./Arrow\";\nimport { Circle } from \"./Circle\";\nimport { Clean } from \"./Clean\";\nimport { Clicker } from \"./Clicker\";\nimport { Collapse } from \"./Collapse\";\nimport { Diamond } from \"./Diamond\";\nimport { Down } from \"./Down\";\nimport { Eraser } from \"./Eraser\";\nimport { Expand } from \"./Expand\";\nimport { Line } from \"./Line\";\nimport { Pencil } from \"./Pencil\";\nimport { Rectangle } from \"./Rectangle\";\nimport { Selector } from \"./Selector\";\nimport { SpeechBalloon } from \"./SpeechBalloon\";\nimport { Star } from \"./Star\";\nimport { Text } from \"./Text\";\nimport { Triangle } from \"./Triangle\";\nimport { Up } from \"./Up\";\n\nexport const Icons = {\n Clicker: memo(Clicker),\n Collapse: memo(Collapse),\n Eraser: memo(Eraser),\n Expand: memo(Expand),\n Pencil: memo(Pencil),\n Selector: memo(Selector),\n Rectangle: memo(Rectangle),\n Text: memo(Text),\n Apps: memo(Apps),\n Clean: memo(Clean),\n Circle: memo(Circle),\n Line: memo(Line),\n Arrow: memo(Arrow),\n Star: memo(Star),\n Diamond: memo(Diamond),\n SpeechBalloon: memo(SpeechBalloon),\n Triangle: memo(Triangle),\n Up: memo(Up),\n Down: memo(Down),\n};\n","import type { Placement } from \"tippy.js\";\n\nimport clsx from \"clsx\";\nimport React, { forwardRef, useContext, type PropsWithChildren } from \"react\";\nimport Tippy from \"@tippyjs/react\";\n\nimport { RightOffset } from \"../../../theme\";\nimport { ToolbarContext } from \"../Toolbar\";\n\ntype ButtonProps = PropsWithChildren<{\n content: React.ReactNode;\n disabled?: boolean;\n active?: boolean;\n onClick?: () => void;\n interactive?: boolean;\n placement?: Placement;\n}>;\n\nexport const Button = forwardRef<HTMLButtonElement, ButtonProps>(\n (props, ref) => {\n const {\n content,\n disabled,\n active,\n onClick,\n interactive,\n placement = \"right\",\n children,\n } = props;\n const { writable, theme } = useContext(ToolbarContext);\n\n return (\n <Tippy\n className=\"fastboard-tip\"\n content={content}\n interactive={interactive}\n theme={theme}\n disabled={disabled || !writable}\n placement={placement}\n offset={placement.includes(\"right\") ? RightOffset : undefined}\n duration={300}\n >\n <button\n ref={ref}\n className={clsx(\"fastboard-toolbar-btn\", theme, { active })}\n onClick={onClick}\n disabled={disabled || !writable}\n >\n {children}\n </button>\n </Tippy>\n );\n }\n);\n","import clsx from \"clsx\";\nimport React, { useContext } from \"react\";\nimport { ToolbarContext, name } from \"../Toolbar\";\n\nexport function CutLine() {\n const { theme } = useContext(ToolbarContext);\n return <span className={clsx(`${name}-cut-line`, theme)} />;\n}\n","import type {\n ApplianceNames,\n Color,\n MemberState,\n Room,\n RoomState,\n ShapeType,\n} from \"white-web-sdk\";\n\nimport { useCallback, useEffect, useState } from \"react\";\nimport { noop } from \"../../internal\";\n\nexport function useWritable(room?: Room | null) {\n const [value, setValue] = useState(false);\n\n useEffect(() => {\n if (room) {\n const setWritable = () => setValue(room.isWritable);\n setWritable();\n room.callbacks.on(\"onEnableWriteNowChanged\", setWritable);\n return () => room.callbacks.off(\"onEnableWriteNowChanged\", setWritable);\n }\n }, [room]);\n\n return value;\n}\n\nexport function useRoomState(room?: Room | null) {\n const [memberState, setMemberState] = useState<MemberState | undefined>(\n undefined\n );\n\n useEffect(() => {\n if (room) {\n setMemberState(room.state.memberState);\n const onRoomStateChanged = (diff: Partial<RoomState>) => {\n if (diff.memberState) setMemberState(diff.memberState);\n };\n room.callbacks.on(\"onRoomStateChanged\", onRoomStateChanged);\n return () => room.callbacks.off(\"onRoomStateChanged\", onRoomStateChanged);\n }\n }, [room]);\n\n return { memberState };\n}\n\nexport interface ToolbarHook {\n readonly writable: boolean;\n readonly memberState: MemberState | undefined;\n cleanCurrentScene(): void;\n setAppliance(appliance: ApplianceNames, shape?: ShapeType): void;\n setStrokeWidth(width: number): void;\n setStrokeColor(color: Color): void;\n}\n\nexport function useToolbar(room?: Room | null): ToolbarHook {\n const writable = useWritable(room);\n const { memberState } = useRoomState(room);\n\n const cleanCurrentScene = useCallback(() => {\n if (room?.isWritable) {\n room.cleanCurrentScene();\n }\n }, [room]);\n\n const setAppliance = useCallback(\n (appliance: ApplianceNames, shape?: ShapeType) => {\n if (room?.isWritable) {\n room.setMemberState({\n currentApplianceName: appliance,\n shapeType: shape,\n });\n }\n },\n [room]\n );\n\n const setStrokeWidth = useCallback(\n (strokeWidth: number) => {\n if (room?.isWritable) {\n room.setMemberState({ strokeWidth });\n }\n },\n [room]\n );\n\n const setStrokeColor = useCallback(\n (strokeColor: Color) => {\n if (room?.isWritable) {\n room.setMemberState({ strokeColor });\n }\n },\n [room]\n );\n\n return {\n writable,\n memberState,\n cleanCurrentScene,\n setAppliance,\n setStrokeWidth,\n setStrokeColor,\n };\n}\n\nexport const EmptyToolbarHook: ToolbarHook = {\n writable: false,\n memberState: undefined,\n cleanCurrentScene: noop,\n setAppliance: noop,\n setStrokeWidth: noop,\n setStrokeColor: noop,\n};\n","import { ApplianceNames, ShapeType } from \"white-web-sdk\";\nimport { Icons } from \"./icons\";\n\nexport const ShapesMap = {\n [ApplianceNames.rectangle]: Icons.Rectangle,\n [ApplianceNames.ellipse]: Icons.Circle,\n [ApplianceNames.straight]: Icons.Line,\n [ApplianceNames.arrow]: Icons.Arrow,\n [ShapeType.Pentagram]: Icons.Star,\n [ShapeType.Rhombus]: Icons.Diamond,\n [ShapeType.Triangle]: Icons.Triangle,\n [ShapeType.SpeechBalloon]: Icons.SpeechBalloon,\n} as const;\n\nexport const ApplianceShapes = [\n ApplianceNames.rectangle,\n ApplianceNames.ellipse,\n ApplianceNames.straight,\n ApplianceNames.arrow,\n] as const;\n\nexport const Shapes = [\n ShapeType.Pentagram,\n ShapeType.Rhombus,\n ShapeType.Triangle,\n ShapeType.SpeechBalloon,\n] as const;\n\nexport const ItemHeight = 32 + 4;\nexport const ItemsCount = 8;\nexport const MaxHeight = ItemHeight * ItemsCount - 4;\nexport const MinHeight = ItemHeight * 2 - 4;\n","import React, { useCallback, useContext } from \"react\";\n\nimport { Icon } from \"../../../icons\";\nimport { Icons } from \"../icons\";\nimport { Button } from \"./Button\";\nimport { CutLine } from \"./CutLine\";\nimport { ToolbarContext } from \"../Toolbar\";\nimport { ItemHeight } from \"../const\";\n\nexport interface UpButtonProps {\n disabled: boolean;\n scrollTo: (height: number) => void;\n}\n\nexport function UpButton({ disabled, scrollTo }: UpButtonProps) {\n const { theme, icons } = useContext(ToolbarContext);\n const scrollUp = useCallback(() => scrollTo(-ItemHeight), [scrollTo]);\n\n return (\n <>\n <Button content=\"Up\" disabled={disabled} onClick={scrollUp}>\n <Icon\n fallback={<Icons.Up theme={theme} />}\n src={disabled ? icons?.upIconDisable : icons?.upIcon}\n alt=\"[up]\"\n />\n </Button>\n <CutLine />\n </>\n );\n}\n\nexport function DownButton({ disabled, scrollTo }: UpButtonProps) {\n const { theme, icons } = useContext(ToolbarContext);\n const scrollDown = useCallback(() => scrollTo(ItemHeight), [scrollTo]);\n\n return (\n <>\n <CutLine />\n <Button content=\"Down\" disabled={disabled} onClick={scrollDown}>\n <Icon\n fallback={<Icons.Down theme={theme} />}\n src={disabled ? icons?.downIconDisable : icons?.downIcon}\n alt=\"[down]\"\n />\n </Button>\n </>\n );\n}\n","import type { HotKey } from \"white-web-sdk\";\n\nimport React, { useCallback, useContext } from \"react\";\nimport { ApplianceNames } from \"white-web-sdk\";\n\nimport { defaultHotKeys, useInstance } from \"../../../internal\";\nimport { Icon } from \"../../../icons\";\nimport { Icons } from \"../icons\";\nimport { ToolbarContext } from \"../Toolbar\";\nimport { Button } from \"./Button\";\n\nexport function renderToolTip(text: string | undefined, hotkey?: HotKey) {\n if (!(typeof hotkey === \"string\")) return text;\n return (\n <span className=\"fastboard-toolbar-tooltip\">\n <span>{text}</span>\n <span className=\"fastboard-toolbar-hotkey\">{hotkey.toUpperCase()}</span>\n </span>\n );\n}\n\nexport function ClickerButton() {\n const app = useInstance();\n\n const { theme, icons, writable, setAppliance, memberState, i18n } =\n useContext(ToolbarContext);\n\n const changeAppliance = useCallback(\n () => setAppliance(ApplianceNames.clicker),\n [setAppliance]\n );\n\n const shortcut = app?.config.joinRoom.hotKeys?.changeToClick;\n const appliance = memberState?.currentApplianceName;\n const active = appliance === ApplianceNames.clicker;\n const disabled = !writable;\n\n return (\n <Button\n content={renderToolTip(i18n?.t(\"clicker\"), shortcut)}\n onClick={changeAppliance}\n active={active}\n >\n <Icon\n fallback={<Icons.Clicker theme={theme} active={active} />}\n src={disabled ? icons?.clickerIconDisable : icons?.clickerIcon}\n alt=\"[clicker]\"\n />\n </Button>\n );\n}\n\nexport function SelectorButton() {\n const app = useInstance();\n\n const { theme, icons, writable, setAppliance, memberState, i18n } =\n useContext(ToolbarContext);\n\n const changeAppliance = useCallback(\n () => setAppliance(ApplianceNames.selector),\n [setAppliance]\n );\n\n const appliance = memberState?.currentApplianceName;\n const active = appliance === ApplianceNames.selector;\n const disabled = !writable;\n const shortcut = (app?.config.joinRoom.hotKeys || defaultHotKeys)\n .changeToSelector;\n\n return (\n <Button\n content={renderToolTip(i18n?.t(\"selector\"), shortcut)}\n onClick={changeAppliance}\n active={active}\n >\n <Icon\n fallback={<Icons.Selector theme={theme} active={active} />}\n src={disabled ? icons?.selectorIconDisable : icons?.selectorIcon}\n alt=\"[selector]\"\n />\n </Button>\n );\n}\n\nexport function EraserButton() {\n const app = useInstance();\n\n const { theme, icons, writable, setAppliance, memberState, i18n } =\n useContext(ToolbarContext);\n\n const changeAppliance = useCallback(\n () => setAppliance(ApplianceNames.eraser),\n [setAppliance]\n );\n\n const appliance = memberState?.currentApplianceName;\n const active = appliance === ApplianceNames.eraser;\n const disabled = !writable;\n const shortcut = (app?.config.joinRoom.hotKeys || defaultHotKeys)\n .changeToEraser;\n\n return (\n <Button\n content={renderToolTip(i18n?.t(\"eraser\"), shortcut)}\n onClick={changeAppliance}\n active={active}\n >\n <Icon\n fallback={<Icons.Eraser theme={theme} active={active} />}\n src={disabled ? icons?.eraserIconDisable : icons?.eraserIcon}\n alt=\"[eraser]\"\n />\n </Button>\n );\n}\n\nexport function CleanButton() {\n const { theme, icons, writable, cleanCurrentScene, i18n } =\n useContext(ToolbarContext);\n\n const disabled = !writable;\n\n return (\n <Button content={i18n?.t(\"clean\")} onClick={cleanCurrentScene}>\n <Icon\n fallback={<Icons.Clean theme={theme} />}\n src={disabled ? icons?.cleanIconDisable : icons?.cleanIcon}\n alt=\"[clean]\"\n />\n </Button>\n );\n}\n","export default \"data:image/png;base64,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\"","export default \"data:image/png;base64,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\"","export default \"data:image/png;base64,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\"","import Tippy from \"@tippyjs/react\";\nimport React, { useContext } from \"react\";\n\nimport vscodePNG from \"./assets/vscode.png\";\nimport geogebraPNG from \"./assets/geogebra.png\";\nimport countdownPNG from \"./assets/countdown.png\";\n\nimport { useInstance } from \"../../../internal\";\nimport { Icon } from \"../../../icons\";\nimport { RightOffset } from \"../../../theme\";\nimport { Icons } from \"../icons\";\nimport { ToolbarContext } from \"../Toolbar\";\nimport { Button } from \"./Button\";\n\nexport interface AppsButtonProps {\n content?: React.ReactNode;\n onClick?: () => void;\n}\n\nexport function AppsButton({ content, onClick }: AppsButtonProps) {\n const { theme, icons, writable } = useContext(ToolbarContext);\n\n const disabled = !writable;\n\n const button = (\n <Button content=\"Apps\" onClick={onClick}>\n <Icon\n fallback={<Icons.Apps theme={theme} />}\n src={disabled ? icons?.appsIconDisable : icons?.appsIcon}\n alt=\"[apps]\"\n />\n </Button>\n );\n\n return content === false ? (\n button\n ) : (\n <span className=\"fastboard-toolbar-btn-interactive\">\n <Tippy\n className=\"fastboard-tip\"\n content={renderAppsButtonContent(content)}\n theme={theme}\n placement=\"right-end\"\n trigger=\"click\"\n offset={RightOffset}\n arrow={false}\n interactive\n >\n {button}\n </Tippy>\n </span>\n );\n}\n\nfunction renderAppsButtonContent(content?: React.ReactNode) {\n return (\n <div className=\"fastboard-toolbar-panel apps\">\n <div className=\"fastboard-toolbar-apps\">{content || <DefaultApps />}</div>\n </div>\n );\n}\n\nfunction DefaultApps() {\n const app = useInstance();\n\n return (\n <>\n <AppIcon\n title=\"Code Editor\"\n src={vscodePNG}\n alt=\"[code editor]\"\n onClick={app?.insertCodeEditor.bind(app)}\n />\n <AppIcon\n title=\"GeoGebra\"\n src={geogebraPNG}\n alt=\"[geogebra]\"\n onClick={app?.insertGeoGebra.bind(app)}\n />\n <AppIcon\n title=\"Countdown\"\n src={countdownPNG}\n alt=\"[countdown]\"\n onClick={app?.insertCountdown.bind(app)}\n />\n </>\n );\n}\n\ninterface AppIconProps {\n title: string;\n src: string;\n alt: string;\n onClick?: () => void;\n}\n\nfunction AppIcon({ title, src, alt, onClick }: AppIconProps) {\n return (\n <span className=\"fastboard-toolbar-app-icon\">\n <Button placement=\"top\" content={title} onClick={onClick}>\n <img src={src} alt={alt} title={title} />\n </Button>\n <span className=\"fastboard-toolbar-app-icon-text\">{title}</span>\n </span>\n );\n}\n","import type { Color } from \"white-web-sdk\";\n\nimport clsx from \"clsx\";\nimport React, { useContext } from \"react\";\n\nimport { isEqualArray } from \"../../../internal\";\nimport { ToolbarContext } from \"../Toolbar\";\n\nconst colors: Record<string, Color> = {\n \"#E02020\": [224, 32, 32],\n \"#F7B500\": [247, 181, 0],\n \"#6DD400\": [109, 212, 0],\n \"#32C5FF\": [50, 197, 255],\n \"#0091FF\": [0, 145, 255],\n \"#6236FF\": [98, 54, 255],\n \"#B620E0\": [182, 32, 224],\n \"#6D7278\": [109, 114, 120],\n};\n\nconst colorKeys = Object.keys(colors);\n\nexport function ColorBox() {\n const { theme, memberState, setStrokeColor, writable } =\n useContext(ToolbarContext);\n\n const strokeColor = memberState?.strokeColor;\n const disabled = !writable;\n\n return (\n <div className={clsx(\"fastboard-toolbar-color-box\", theme)}>\n {colorKeys.map((key: string) => (\n <div\n key={key}\n className={clsx(\"fastboard-toolbar-color-item\", theme)}\n onClick={() => setStrokeColor(colors[key])}\n >\n <div\n className={clsx(\"fastboard-toolbar-color-border\", theme, {\n active: strokeColor && isEqualArray(strokeColor, colors[key]),\n })}\n >\n <button\n className={clsx(\"fastboard-toolbar-color-btn\")}\n style={{ background: key }}\n disabled={disabled}\n onClick={ev => {\n ev.stopPropagation();\n setStrokeColor(colors[key]);\n }}\n />\n </div>\n </div>\n ))}\n </div>\n );\n}\n","import clsx from \"clsx\";\nimport RcSlider from \"rc-slider\";\nimport React, { useContext } from \"react\";\n\nimport { themes } from \"../../../theme\";\nimport { ToolbarContext } from \"../Toolbar\";\n\nexport function Slider() {\n const { theme, writable, memberState, setStrokeWidth } =\n useContext(ToolbarContext);\n const { activeColor } = themes[theme];\n\n const strokeWidth = memberState?.strokeWidth || 0;\n\n return (\n <RcSlider\n disabled={!writable}\n className={clsx(\"fastboard-toolbar-slider\", theme)}\n trackStyle={{ background: activeColor }}\n handleStyle={{ border: `1px solid ${activeColor}` }}\n value={strokeWidth}\n onChange={setStrokeWidth}\n min={1}\n max={32}\n />\n );\n}\n","import Tippy from \"@tippyjs/react\";\nimport React, { useCallback } from \"react\";\nimport { useContext } from \"react\";\nimport { ApplianceNames } from \"white-web-sdk\";\n\nimport { defaultHotKeys, useInstance } from \"../../../internal\";\nimport { Icon } from \"../../../icons\";\nimport { RightOffset } from \"../../../theme\";\nimport { Icons } from \"../icons\";\nimport { ToolbarContext } from \"../Toolbar\";\nimport { Button } from \"./Button\";\nimport { ColorBox } from \"./ColorBox\";\nimport { CutLine } from \"./CutLine\";\nimport { Slider } from \"./Slider\";\nimport { renderToolTip } from \"./ApplianceButtons\";\n\nexport function PencilButton() {\n const app = useInstance();\n\n const { theme, icons, writable, setAppliance, memberState, i18n } =\n useContext(ToolbarContext);\n\n const changeAppliance = useCallback(() => {\n setAppliance(ApplianceNames.pencil);\n }, [setAppliance]);\n\n const appliance = memberState?.currentApplianceName;\n const active = appliance === ApplianceNames.pencil;\n const disabled = !writable;\n const shortcut = (app?.config.joinRoom.hotKeys || defaultHotKeys)\n .changeToPencil;\n\n return (\n <span className=\"fastboard-toolbar-btn-interactive\">\n <Tippy\n className=\"fastboard-tip\"\n content={renderPencilButtonContent()}\n theme={theme}\n placement=\"right-start\"\n trigger=\"click\"\n offset={RightOffset}\n arrow={false}\n interactive\n >\n <Button\n content={renderToolTip(i18n?.t(\"pencil\"), shortcut)}\n active={active}\n onClick={changeAppliance}\n >\n <Icon\n fallback={<Icons.Pencil theme={theme} active={active} />}\n src={disabled ? icons?.pencilIconDisable : icons?.pencilIcon}\n alt=\"[pencil]\"\n />\n <span className=\"fastboard-toolbar-triangle\" />\n </Button>\n </Tippy>\n </span>\n );\n}\n\nfunction renderPencilButtonContent() {\n return (\n <div className=\"fastboard-toolbar-panel pencil\">\n <Slider />\n <CutLine />\n <ColorBox />\n </div>\n );\n}\n","import Tippy from \"@tippyjs/react\";\nimport React, { useCallback } from \"react\";\nimport { useContext } from \"react\";\nimport { ApplianceNames } from \"white-web-sdk\";\n\nimport { defaultHotKeys, useInstance } from \"../../../internal\";\nimport { Icon } from \"../../../icons\";\nimport { RightOffset } from \"../../../theme\";\nimport { Icons } from \"../icons\";\nimport { ToolbarContext } from \"../Toolbar\";\nimport { Button } from \"./Button\";\nimport { ColorBox } from \"./ColorBox\";\nimport { renderToolTip } from \"./ApplianceButtons\";\n\nexport function TextButton() {\n const app = useInstance();\n\n const { theme, icons, writable, setAppliance, memberState, i18n } =\n useContext(ToolbarContext);\n\n const changeAppliance = useCallback(() => {\n setAppliance(ApplianceNames.text);\n }, [setAppliance]);\n\n const appliance = memberState?.currentApplianceName;\n const active = appliance === ApplianceNames.text;\n const disabled = !writable;\n const shortcut = (app?.config.joinRoom.hotKeys || defaultHotKeys)\n .changeToText;\n\n return (\n <span className=\"fastboard-toolbar-btn-interactive\">\n <Tippy\n className=\"fastboard-tip\"\n content={renderTextButtonContent()}\n theme={theme}\n placement=\"right-start\"\n trigger=\"click\"\n offset={RightOffset}\n arrow={false}\n interactive\n >\n <Button\n content={renderToolTip(i18n?.t(\"text\"), shortcut)}\n active={active}\n onClick={changeAppliance}\n >\n <Icon\n fallback={<Icons.Text theme={theme} active={active} />}\n src={disabled ? icons?.textIconDisable : icons?.textIcon}\n alt=\"[text]\"\n />\n <span className=\"fastboard-toolbar-triangle\" />\n </Button>\n </Tippy>\n </span>\n );\n}\n\nfunction renderTextButtonContent() {\n return (\n <div className=\"fastboard-toolbar-panel text\">\n <ColorBox />\n </div>\n );\n}\n","import type { IconProps } from \"../../../types\";\n\nimport Tippy from \"@tippyjs/react\";\nimport React, { useContext } from \"react\";\nimport type { ShapeType } from \"white-web-sdk\";\nimport { ApplianceNames } from \"white-web-sdk\";\n\nimport { RightOffset } from \"../../../theme\";\nimport { ApplianceShapes, Shapes, ShapesMap } from \"../const\";\nimport { Icons } from \"../icons\";\nimport { ToolbarContext } from \"../Toolbar\";\nimport { Button } from \"./Button\";\nimport { CutLine } from \"./CutLine\";\nimport { Slider } from \"./Slider\";\nimport { ColorBox } from \"./ColorBox\";\n\nconst ShapeTypes = new Set([...ApplianceShapes, ...Shapes]);\n\nexport function ShapesButton() {\n const { theme, memberState, i18n } = useContext(ToolbarContext);\n\n const appliance = memberState?.currentApplianceName;\n const shape = memberState?.shapeType;\n\n const key = (\n appliance === ApplianceNames.shape ? shape : appliance\n ) as keyof typeof ShapesMap;\n\n const active = ShapeTypes.has(key);\n\n const CurrentIcon = ShapesMap[key] || Icons.Rectangle;\n\n return (\n <span className=\"fastboard-toolbar-btn-interactive\">\n <Tippy\n className=\"fastboard-tip\"\n content={renderShapesButtonContent()}\n theme={theme}\n placement=\"right-start\"\n trigger=\"click\"\n offset={RightOffset}\n arrow={false}\n interactive\n >\n <Button content={i18n?.t(\"shape\")} active={active}>\n <CurrentIcon theme={theme} active={active} />\n <span className=\"fastboard-toolbar-triangle\" />\n </Button>\n </Tippy>\n </span>\n );\n}\n\nfunction renderShapesButtonContent() {\n return (\n <div className=\"fastboard-toolbar-panel shapes\">\n <ShapesBox />\n <CutLine />\n <Slider />\n <CutLine />\n <ColorBox />\n </div>\n );\n}\n\nexport function ShapesBox() {\n const { i18n } = useContext(ToolbarContext);\n return (\n <div className=\"fastboard-toolbar-shapes\">\n {ApplianceShapes.map(Appliance => (\n <ApplianceShapeButton\n key={Appliance}\n content={i18n?.t(Appliance)}\n Appliance={Appliance}\n Icon={ShapesMap[Appliance]}\n />\n ))}\n {Shapes.map(shape => (\n <ShapeShapeButton\n key={shape}\n content={i18n?.t(shape)}\n shape={shape}\n Icon={ShapesMap[shape]}\n />\n ))}\n </div>\n );\n}\n\ninterface ApplianceShapeButtonProps {\n content?: string;\n Appliance: ApplianceNames;\n Icon: React.ComponentType<IconProps>;\n}\n\nfunction ApplianceShapeButton({\n content,\n Appliance,\n Icon,\n}: ApplianceShapeButtonProps) {\n const { theme, writable, setAppliance, memberState } =\n useContext(ToolbarContext);\n\n const current = memberState?.currentApplianceName;\n const disabled = !writable;\n\n return (\n <Button\n content={content}\n disabled={disabled}\n placement=\"top\"\n onClick={() => setAppliance(Appliance)}\n >\n <Icon theme={theme} active={current === Appliance} />\n </Button>\n );\n}\n\ninterface ShapeShapeButtonProps {\n content?: string;\n shape: ShapeType;\n Icon: React.ComponentType<IconProps>;\n}\n\nfunction ShapeShapeButton({ content, shape, Icon }: ShapeShapeButtonProps) {\n const { theme, writable, setAppliance, memberState } =\n useContext(ToolbarContext);\n\n const appliance = memberState?.currentApplianceName;\n const current = appliance === ApplianceNames.shape && memberState?.shapeType;\n const disabled = !writable;\n\n return (\n <Button\n content={content}\n disabled={disabled}\n placement=\"top\"\n onClick={() => setAppliance(ApplianceNames.shape, shape)}\n >\n <Icon theme={theme} active={current === shape} />\n </Button>\n );\n}\n","import React, { useCallback, useEffect, useRef, useState } from \"react\";\n\nimport { useInstance, clamp } from \"../../internal\";\nimport { name } from \"./Toolbar\";\nimport { ItemHeight, ItemsCount, MaxHeight, MinHeight } from \"./const\";\nimport { DownButton, UpButton } from \"./components/UpDownButtons\";\nimport {\n CleanButton,\n ClickerButton,\n EraserButton,\n SelectorButton,\n} from \"./components/ApplianceButtons\";\nimport { AppsButton } from \"./components/AppsButton\";\nimport { PencilButton } from \"./components/PencilButton\";\nimport { TextButton } from \"./components/TextButton\";\nimport { ShapesButton } from \"./components/ShapesButton\";\n\nexport function Content() {\n const app = useInstance();\n const ref = useRef<HTMLDivElement>(null);\n const [scrollTop, setScrollTop] = useState(0);\n const [parentHeight, setParentHeight] = useState(0);\n\n const hasAppButton = app?.config.toolbar?.apps?.enable ?? true;\n const needScroll = parentHeight < ItemHeight * ItemsCount + 48;\n const sectionHeight = clamp(\n parentHeight - 48 * (needScroll ? 3 : 1),\n MinHeight,\n MaxHeight\n );\n const scrollBuffer = Math.max(parentHeight - sectionHeight - 1, 0);\n const disableScrollUp = scrollTop === 0;\n const disableScrollDown = scrollTop === scrollBuffer;\n\n const scrollTo = useCallback(\n (height: number) => {\n setScrollTop(clamp(scrollTop + height, 0, scrollBuffer));\n },\n [scrollBuffer, scrollTop]\n );\n\n useEffect(() => {\n if (ref.current) {\n ref.current.scrollTop = scrollTop;\n }\n }, [scrollTop]);\n\n useEffect(() => {\n const container = ref.current?.parentElement?.parentElement;\n if (container) {\n const { paddingTop, paddingBottom } = getComputedStyle(container);\n const padding = parseInt(paddingTop) + parseInt(paddingBottom) || 0;\n const resizeObserver = new ResizeObserver(() => {\n setParentHeight(container.getBoundingClientRect().height - padding);\n });\n resizeObserver.observe(container);\n return () => resizeObserver.disconnect();\n }\n }, []);\n\n return (\n <>\n {needScroll && (\n <UpButton scrollTo={scrollTo} disabled={disableScrollUp} />\n )}\n <div\n ref={ref}\n className={`${name}-section`}\n style={{\n height: `${sectionHeight}px`,\n overflow: needScroll ? \"hidden\" : \"visible\",\n }}\n >\n <ClickerButton />\n <SelectorButton />\n <PencilButton />\n <TextButton />\n <ShapesButton />\n <EraserButton />\n <CleanButton />\n {hasAppButton && (\n <AppsButton\n content={app?.config.toolbar?.apps?.content}\n onClick={app?.config.toolbar?.apps?.onClick}\n />\n )}\n </div>\n {needScroll && (\n <DownButton scrollTo={scrollTo} disabled={disableScrollDown} />\n )}\n </>\n );\n}\n","import type { CommonProps, GenericIcon, Theme } from \"../../types\";\nimport type { i18n } from \"i18next\";\n\nimport clsx from \"clsx\";\nimport React, { createContext, useCallback, useState } from \"react\";\n\nimport { Icon } from \"../../icons\";\nimport { Icons } from \"./icons\";\nimport { Button } from \"./components/Button\";\nimport { CutLine } from \"./components/CutLine\";\nimport { EmptyToolbarHook, useToolbar, type ToolbarHook } from \"./hooks\";\nimport { Content } from \"./Content\";\n\nexport type ToolbarProps = CommonProps & {\n icons?: GenericIcon<\n | \"clicker\"\n | \"selector\"\n | \"pencil\"\n | \"eraser\"\n | \"clean\"\n | \"expand\"\n | \"collapse\"\n | \"up\"\n | \"down\"\n | \"text\"\n | \"apps\"\n >;\n};\n\ntype ToolbarContextType = ToolbarHook & {\n theme: Theme;\n icons?: ToolbarProps[\"icons\"];\n i18n?: i18n | null;\n};\n\nexport const ToolbarContext = createContext<ToolbarContextType>({\n theme: \"light\",\n ...EmptyToolbarHook,\n});\n\nexport const name = \"fastboard-toolbar\";\n\nexport const Toolbar = ({\n theme = \"light\",\n icons,\n room,\n i18n,\n}: ToolbarProps) => {\n const [expanded, setExpanded] = useState(true);\n const hook = useToolbar(room);\n const toggle = useCallback(() => setExpanded(e => !e), []);\n\n const disabled = !hook.writable;\n\n return (\n <ToolbarContext.Provider value={{ theme, icons, ...hook, i18n }}>\n <div className={clsx(name, theme)}>\n {expanded ? (\n <Button content={i18n?.t(\"collapse\")} onClick={toggle}>\n <Icon\n fallback={<Icons.Collapse theme={theme} />}\n src={disabled ? icons?.collapseIconDisable : icons?.collapseIcon}\n />\n </Button>\n ) : (\n <Button content={i18n?.t(\"expand\")} onClick={toggle}>\n <Icon\n fallback={<Icons.Expand theme={theme} />}\n src={disabled ? icons?.expandIconDisable : icons?.expandIcon}\n />\n </Button>\n )}\n {expanded && (\n <>\n <CutLine />\n <Content />\n </>\n )}\n </div>\n </ToolbarContext.Provider>\n );\n};\n","import type { IconProps } from \"../types\";\n\nimport React from \"react\";\nimport { themes } from \"../theme\";\n\nexport function Undo({ theme = \"light\", active }: IconProps) {\n const config = themes[theme];\n const stroke = active ? config.activeColor : config.color;\n\n return (\n <svg viewBox=\"0 0 24 24\">\n <g\n fill=\"none\"\n fillRule=\"evenodd\"\n stroke={stroke}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"M10 14H6v-4\" />\n <path d=\"m6 14 .788-.9A7.005 7.005 0 0 1 18 14h0\" />\n </g>\n </svg>\n );\n}\n","import type { IconProps } from \"../types\";\n\nimport React from \"react\";\nimport { themes } from \"../theme\";\n\nexport function Redo({ theme = \"light\", active }: IconProps) {\n const config = themes[theme];\n const stroke = active ? config.activeColor : config.color;\n\n return (\n <svg viewBox=\"0 0 24 24\">\n <g\n fill=\"none\"\n fillRule=\"evenodd\"\n stroke={stroke}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"M14 14h4v-4\" />\n <path d=\"m18 14-.788-.9A7.005 7.005 0 0 0 6 14h0\" />\n </g>\n </svg>\n );\n}\n","import type { CommonProps, GenericIcon } from \"../types\";\n\nimport clsx from \"clsx\";\nimport React, { useCallback, useEffect, useState } from \"react\";\nimport Tippy from \"@tippyjs/react\";\n\nimport { Icon } from \"../icons\";\nimport { Undo } from \"../icons/Undo\";\nimport { Redo } from \"../icons/Redo\";\nimport { TopOffset } from \"../theme\";\n\nexport const name = \"fastboard-redo-undo\";\n\nexport type RedoUndoProps = CommonProps & GenericIcon<\"undo\" | \"redo\">;\n\nexport function RedoUndo({\n room,\n theme = \"light\",\n undoIcon,\n undoIconDisable,\n redoIcon,\n redoIconDisable,\n i18n,\n}: RedoUndoProps) {\n const [writable, setWritable] = useState(false);\n const [undoSteps, setUndoSteps] = useState(0);\n const [redoSteps, setRedoSteps] = useState(0);\n\n useEffect(() => {\n if (room) {\n setWritable(room.isWritable);\n room.isWritable && (room.disableSerialization = false);\n\n const updateWritable = () => setWritable(room?.isWritable || false);\n\n room.callbacks.on(\"onEnableWriteNowChanged\", updateWritable);\n room.callbacks.on(\"onCanUndoStepsUpdate\", setUndoSteps);\n room.callbacks.on(\"onCanRedoStepsUpdate\", setRedoSteps);\n return () => {\n room.callbacks.off(\"onEnableWriteNowChanged\", updateWritable);\n room.callbacks.off(\"onCanUndoStepsUpdate\", setUndoSteps);\n room.callbacks.off(\"onCanRedoStepsUpdate\", setRedoSteps);\n };\n }\n }, [room]);\n\n const disabled = !writable;\n\n return (\n <div className={clsx(name, theme)}>\n <Tippy\n className=\"fastboard-tip\"\n content={i18n?.t(\"undo\")}\n theme={theme}\n disabled={disabled}\n placement=\"top\"\n duration={300}\n offset={TopOffset}\n >\n <button\n className={clsx(`${name}-btn`, \"undo\", theme)}\n disabled={disabled || undoSteps === 0}\n onClick={useCallback(() => room && room.undo(), [room])}\n >\n <Icon\n fallback={<Undo theme={theme} />}\n src={undoSteps === 0 ? undoIconDisable : undoIcon}\n alt=\"[undo]\"\n />\n </button>\n </Tippy>\n <Tippy\n className=\"fastboard-tip\"\n content={i18n?.t(\"redo\")}\n theme={theme}\n disabled={disabled}\n placement=\"top\"\n duration={300}\n offset={TopOffset}\n >\n <button\n className={clsx(`${name}-btn`, \"redo\", theme)}\n disabled={disabled || redoSteps === 0}\n onClick={useCallback(() => room && room.redo(), [room])}\n >\n <Icon\n fallback={<Redo theme={theme} />}\n src={redoSteps === 0 ? redoIconDisable : redoIcon}\n alt=\"[redo]\"\n />\n </button>\n </Tippy>\n </div>\n );\n}\n","import type { IconProps } from \"../types\";\n\nimport React from \"react\";\nimport { themes } from \"../theme\";\n\nexport function Minus({ theme = \"light\", active }: IconProps) {\n const config = themes[theme];\n const stroke = active ? config.activeColor : config.color;\n\n return (\n <svg viewBox=\"0 0 24 24\">\n <path\n fill=\"none\"\n stroke={stroke}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"M7 12h10\"\n />\n </svg>\n );\n}\n","import type { IconProps } from \"../types\";\n\nimport React from \"react\";\nimport { themes } from \"../theme\";\n\nexport function Plus({ theme = \"light\", active }: IconProps) {\n const config = themes[theme];\n const stroke = active ? config.activeColor : config.color;\n\n return (\n <svg viewBox=\"0 0 24 24\">\n <path\n fill=\"none\"\n stroke={stroke}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"M12 7v10m-5-5h10\"\n />\n </svg>\n );\n}\n","import type { IconProps } from \"../types\";\n\nimport React from \"react\";\nimport { themes } from \"../theme\";\n\nexport function Reset({ theme = \"light\", active }: IconProps) {\n const config = themes[theme];\n const stroke = active ? config.activeColor : config.color;\n\n return (\n <svg viewBox=\"0 0 24 24\">\n <g fill=\"none\" fillRule=\"evenodd\" transform=\"translate(-176 -684)\">\n <path\n stroke={stroke}\n strokeLinejoin=\"round\"\n d=\"M188 688v4m0 8v4m8-8h-4m-8 0h-4\"\n />\n <circle cx=\"188\" cy=\"696\" r=\"6\" stroke={stroke} />\n <circle cx=\"188\" cy=\"696\" r=\"1\" fill={stroke} />\n </g>\n </svg>\n );\n}\n","import type { RoomState } from \"white-web-sdk\";\nimport type { CommonProps, GenericIcon } from \"../types\";\n\nimport clsx from \"clsx\";\nimport React, { useCallback, useEffect, useState } from \"react\";\nimport Tippy from \"@tippyjs/react\";\n\nimport { clamp } from \"../internal\";\nimport { TopOffset } from \"../theme\";\nimport { Icon } from \"../icons\";\nimport { Minus } from \"../icons/Minus\";\nimport { Plus } from \"../icons/Plus\";\nimport { Reset } from \"../icons/Reset\";\n\nexport const name = \"fastboard-zoom-control\";\n\nexport const ScalePoints: readonly number[] = [\n 0.10737418240000011, 0.13421772800000012, 0.16777216000000014,\n 0.20971520000000016, 0.26214400000000015, 0.3276800000000002,\n 0.4096000000000002, 0.5120000000000001, 0.6400000000000001, 0.8, 1, 1.26,\n 1.5876000000000001, 2.000376, 2.5204737600000002, 3.1757969376000004,\n 4.001504141376, 5.041895218133761, 6.352787974848539, 8.00451284830916, 10,\n];\n\nfunction nextScale(scale: number, delta: 1 | -1) {\n const { length } = ScalePoints;\n const last = length - 1;\n if (scale < ScalePoints[0]) return ScalePoints[0];\n if (scale > ScalePoints[last]) return ScalePoints[last];\n for (let i = 0; i < length; ++i) {\n const curr = ScalePoints[i];\n const prev = i === 0 ? -Infinity : (ScalePoints[i - 1] + curr) / 2;\n const next = i === last ? Infinity : (ScalePoints[i + 1] + curr) / 2;\n if (prev <= scale && scale <= next)\n return ScalePoints[clamp(i + delta, 0, last)];\n }\n return 1;\n}\n\nexport type ZoomControlProps = CommonProps &\n GenericIcon<\"reset\" | \"minus\" | \"plus\">;\n\nexport function ZoomControl({\n room,\n manager,\n theme = \"light\",\n resetIcon,\n resetIconDisable,\n minusIcon,\n minusIconDisable,\n plusIcon,\n plusIconDisable,\n i18n,\n}: ZoomControlProps) {\n const [writable, setWritable] = useState(false);\n const [scale, setScale] = useState(1);\n\n const resetCamera = useCallback(() => {\n if (room?.isWritable) {\n if (manager) {\n manager.mainView.moveCamera({ scale: 1, centerX: 0, centerY: 0 });\n } else {\n const { scenes, index } = room.state.sceneState;\n if (scenes[index].ppt) {\n room.scalePptToFit();\n } else {\n room.moveCamera({ scale: 1, centerX: 0, centerY: 0 });\n }\n }\n }\n }, [room, manager]);\n\n const zoomIn = useCallback(() => {\n if (room?.isWritable) {\n if (manager) {\n manager.mainView.moveCamera({\n scale: nextScale(scale, 1),\n centerX: 0,\n centerY: 0,\n });\n } else {\n room.moveCamera({\n scale: nextScale(scale, 1),\n centerX: 0,\n centerY: 0,\n });\n }\n }\n }, [room, manager, scale]);\n\n const zoomOut = useCallback(() => {\n if (room?.isWritable) {\n if (manager) {\n manager.mainView.moveCamera({\n scale: nextScale(scale, -1),\n centerX: 0,\n centerY: 0,\n });\n } else {\n room.moveCamera({\n scale: nextScale(scale, -1),\n centerX: 0,\n centerY: 0,\n });\n }\n }\n }, [room, manager, scale]);\n\n useEffect(() => {\n if (room) {\n setWritable(room.isWritable);\n setScale(room.state.cameraState.scale);\n }\n\n if (manager) {\n setScale(manager.mainView.camera.scale);\n }\n\n const onRoomStateChanged = (modifyState: Partial<RoomState>) => {\n if (modifyState.cameraState) {\n setScale(modifyState.cameraState.scale);\n }\n };\n\n const onCameraUpdated = ({ scale }: { scale: number }) => setScale(scale);\n\n const updateWritable = () => setWritable(room?.isWritable || false);\n\n if (room) {\n room.callbacks.on(\"onEnableWriteNowChanged\", updateWritable);\n if (manager) {\n manager.mainView.callbacks.on(\"onCameraUpdated\", onCameraUpdated);\n } else {\n room.callbacks.on(\"onRoomStateChanged\", onRoomStateChanged);\n }\n }\n\n return () => {\n if (room) {\n room.callbacks.off(\"onEnableWriteNowChanged\", updateWritable);\n room.callbacks.off(\"onRoomStateChanged\", onRoomStateChanged);\n manager?.mainView.callbacks.off(\"onCameraUpdated\", onCameraUpdated);\n }\n };\n }, [room, manager]);\n\n const disabled = !writable;\n\n return (\n <div className={clsx(name, theme)}>\n {/* <span className={clsx(`${name}-cut-line`, theme)} /> */}\n <Tippy\n className=\"fastboard-tip\"\n content={i18n?.t(\"zoomOut\")}\n theme={theme}\n disabled={disabled}\n placement=\"top\"\n duration={300}\n offset={TopOffset}\n >\n <button\n className={clsx(`${name}-btn`, \"minus\", theme)}\n disabled={disabled}\n onClick={zoomOut}\n >\n <Icon\n fallback={<Minus theme={theme} />}\n src={disabled ? minusIconDisable : minusIcon}\n alt=\"[minus]\"\n />\n </button>\n </Tippy>\n <span className={clsx(`${name}-scale`, theme)}>\n {Math.ceil(scale * 100)}\n </span>\n <span className={clsx(`${name}-percent`, theme)}>%</span>\n <Tippy\n className=\"fastboard-tip\"\n content={i18n?.t(\"zoomIn\")}\n theme={theme}\n disabled={disabled}\n placement=\"top\"\n duration={300}\n offset={TopOffset}\n >\n <button\n className={clsx(`${name}-btn`, \"plus\", theme)}\n disabled={disabled}\n onClick={zoomIn}\n >\n <Icon\n fallback={<Plus theme={theme} />}\n src={disabled ? plusIconDisable : plusIcon}\n alt=\"[plus]\"\n />\n </button>\n </Tippy>\n <Tippy\n className=\"fastboard-tip\"\n content={i18n?.t(\"reset\")}\n theme={theme}\n disabled={disabled}\n placement=\"top\"\n duration={300}\n offset={TopOffset}\n >\n <button\n className={clsx(`${name}-btn`, \"reset\", theme)}\n disabled={disabled}\n onClick={resetCamera}\n >\n <Icon\n fallback={<Reset theme={theme} />}\n src={disabled ? resetIconDisable : resetIcon}\n alt=\"[reset]\"\n />\n </button>\n </Tippy>\n </div>\n );\n}\n","import type { IconProps } from \"../types\";\n\nimport React from \"react\";\nimport { themes } from \"../theme\";\n\nexport function FilePlus({ theme = \"light\", active }: IconProps) {\n const config = themes[theme];\n const stroke = active ? config.activeColor : config.color;\n\n return (\n <svg viewBox=\"0 0 24 24\">\n <path\n fill={stroke}\n d=\"M12 7.5a.5.5 0 0 1 .09.992L12 8.5H8a1.5 1.5 0 0 0-1.493 1.356L6.5 10v6a1.5 1.5 0 0 0 1.356 1.493L8 17.5h6a1.5 1.5 0 0 0 1.493-1.356L15.5 16v-4a.5.5 0 0 1 .992-.09l.008.09v4a2.5 2.5 0 0 1-2.336 2.495L14 18.5H8a2.5 2.5 0 0 1-2.495-2.336L5.5 16v-6a2.5 2.5 0 0 1 2.336-2.495L8 7.5h4Zm4-2a.5.5 0 0 1 .492.41L16.5 6v1.5H18a.5.5 0 0 1 .09.992L18 8.5h-1.5V10a.5.5 0 0 1-.992.09L15.5 10V8.5H14a.5.5 0 0 1-.09-.992L14 7.5h1.5V6a.5.5 0 0 1 .5-.5Z\"\n />\n </svg>\n );\n}\n","import type { IconProps } from \"../types\";\n\nimport React from \"react\";\nimport { themes } from \"../theme\";\n\nexport function ChevronLeft({ theme = \"light\", active }: IconProps) {\n const config = themes[theme];\n const stroke = active ? config.activeColor : config.color;\n\n return (\n <svg viewBox=\"0 0 24 24\">\n <path\n fill=\"none\"\n stroke={stroke}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"m14 16-2-2-2-2 2-2 2-2\"\n />\n </svg>\n );\n}\n","import type { IconProps } from \"../types\";\n\nimport React from \"react\";\nimport { themes } from \"../theme\";\n\nexport function ChevronRight({ theme = \"light\", active }: IconProps) {\n const config = themes[theme];\n const stroke = active ? config.activeColor : config.color;\n\n return (\n <svg viewBox=\"0 0 24 24\">\n <path\n fill=\"none\"\n stroke={stroke}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"m10 16 2-2 2-2-2-2-2-2\"\n />\n </svg>\n );\n}\n","import type { RoomState, ViewVisionMode } from \"white-web-sdk\";\nimport type { CommonProps, GenericIcon } from \"../types\";\n\nimport clsx from \"clsx\";\nimport React, { useCallback, useEffect, useState } from \"react\";\nimport Tippy from \"@tippyjs/react\";\n\nimport { TopOffset } from \"../theme\";\nimport { Icon } from \"../icons\";\nimport { FilePlus } from \"../icons/FilePlus\";\nimport { ChevronLeft } from \"../icons/ChevronLeft\";\nimport { ChevronRight } from \"../icons/ChevronRight\";\n\nexport const name = \"fastboard-page-control\";\n\nexport type PageControlProps = CommonProps &\n GenericIcon<\"add\" | \"prev\" | \"next\">;\n\nexport function PageControl({\n room,\n manager,\n theme = \"light\",\n addIcon,\n addIconDisable,\n prevIcon,\n prevIconDisable,\n nextIcon,\n nextIconDisable,\n i18n,\n}: PageControlProps) {\n const [writable, setWritable] = useState(false);\n const [pageIndex, setPageIndex] = useState(0);\n const [pageCount, setPageCount] = useState(0);\n\n const addPage = useCallback(async () => {\n if (manager && room) {\n await manager.switchMainViewToWriter();\n const path = room.state.sceneState.contextPath;\n room.putScenes(path, [{}], pageIndex + 1);\n await manager.setMainViewSceneIndex(pageIndex + 1);\n } else if (!manager && room) {\n const path = room.state.sceneState.contextPath;\n room.putScenes(path, [{}], pageIndex + 1);\n room.setSceneIndex(pageIndex + 1);\n }\n }, [room, manager, pageIndex]);\n\n const prevPage = useCallback(() => {\n if (room?.isWritable) {\n if (manager) {\n manager.setMainViewSceneIndex(pageIndex - 1);\n } else {\n room.pptPreviousStep();\n }\n }\n }, [room, manager, pageIndex]);\n\n const nextPage = useCallback(() => {\n if (room?.isWritable) {\n if (manager) {\n manager.setMainViewSceneIndex(pageIndex + 1);\n } else {\n room.pptNextStep();\n }\n }\n }, [room, manager, pageIndex]);\n\n useEffect(() => {\n if (room) {\n setWritable(room.isWritable);\n setPageIndex(room.state.sceneState.index);\n setPageCount(room.state.sceneState.scenes.length);\n }\n\n const onRoomStateChanged = (modifyState: Partial<RoomState>) => {\n if (modifyState.sceneState) {\n setPageIndex(modifyState.sceneState.index);\n setPageCount(modifyState.sceneState.scenes.length);\n }\n };\n\n const onMainViewModeChanged = (mode: number) => {\n if (room && mode === (0 as ViewVisionMode.Writable)) {\n setPageIndex(room.state.sceneState.index);\n setPageCount(room.state.sceneState.scenes.length);\n }\n };\n\n const updateWritable = () => setWritable(room?.isWritable || false);\n\n if (room) {\n room.callbacks.on(\"onEnableWriteNowChanged\", updateWritable);\n room.callbacks.on(\"onRoomStateChanged\", onRoomStateChanged);\n manager?.callbacks.on(\"mainViewModeChange\", onMainViewModeChanged);\n }\n\n return () => {\n if (room) {\n room.callbacks.off(\"onEnableWriteNowChanged\", updateWritable);\n room.callbacks.off(\"onRoomStateChanged\", onRoomStateChanged);\n manager?.callbacks.off(\"mainViewModeChange\", onMainViewModeChanged);\n }\n };\n }, [room, manager]);\n\n const disabled = !writable;\n\n return (\n <div className={clsx(name, theme)}>\n {/* <span className={clsx(`${name}-cut-line`, theme)} />{\" \"} */}\n <Tippy\n className=\"fastboard-tip\"\n content={i18n?.t(\"prevPage\")}\n theme={theme}\n disabled={disabled}\n placement=\"top\"\n duration={300}\n offset={TopOffset}\n >\n <button\n className={clsx(`${name}-btn`, \"prev\", theme)}\n disabled={disabled || pageIndex === 0}\n onClick={prevPage}\n >\n <Icon\n fallback={<ChevronLeft theme={theme} />}\n src={disabled ? prevIconDisable : prevIcon}\n alt=\"[prev]\"\n />\n </button>\n </Tippy>\n <span className={clsx(`${name}-page`, theme)}>\n {pageCount === 0 ? \"\\u2026\" : pageIndex + 1}\n </span>\n <span className={clsx(`${name}-slash`, theme)}>/</span>\n <span className={clsx(`${name}-page-count`, theme)}>{pageCount}</span>\n <Tippy\n className=\"fastboard-tip\"\n content={i18n?.t(\"nextPage\")}\n theme={theme}\n disabled={disabled}\n placement=\"top\"\n duration={300}\n offset={TopOffset}\n >\n <button\n className={clsx(`${name}-btn`, \"next\", theme)}\n disabled={disabled || pageIndex === pageCount - 1}\n onClick={nextPage}\n >\n <Icon\n fallback={<ChevronRight theme={theme} />}\n src={disabled ? nextIconDisable : nextIcon}\n alt=\"[next]\"\n />\n </button>\n </Tippy>\n <Tippy\n className=\"fastboard-tip\"\n content={i18n?.t(\"addPage\")}\n theme={theme}\n disabled={disabled}\n placement=\"top\"\n duration={300}\n offset={TopOffset}\n >\n <button\n className={clsx(`${name}-btn`, \"add\", theme)}\n disabled={disabled}\n onClick={addPage}\n >\n <Icon\n fallback={<FilePlus theme={theme} />}\n src={disabled ? addIconDisable : addIcon}\n alt=\"[add]\"\n />\n </button>\n </Tippy>\n </div>\n );\n}\n","import React, { useCallback, useState } from \"react\";\n\nimport { Lock, Instance } from \"../internal\";\nimport { Toolbar } from \"./Toolbar\";\nimport { RedoUndo } from \"./RedoUndo\";\nimport { ZoomControl } from \"./ZoomControl\";\nimport { PageControl } from \"./PageControl\";\n\nexport interface RootProps {\n instance: Instance;\n}\n\nexport function Root({ instance: app }: RootProps) {\n const [mux] = useState(() => new Lock());\n\n const useWhiteboard = useCallback(\n (container: HTMLDivElement | null) =>\n mux.schedule(\n container ? () => app.mount(container) : () => app.unmount()\n ),\n [app, mux]\n );\n\n const {\n Toolbar: toolbar = true,\n RedoUndo: redo_undo = true,\n ZoomControl: zoom_control = true,\n PageControl: page_control = true,\n } = app.config.layout || {};\n\n const props = {\n room: app.room,\n manager: app.manager,\n i18n: app.i18n,\n };\n\n return (\n <Instance.Context.Provider value={app}>\n <div className=\"fastboard-root\">\n {!app.room && <div className=\"fastboard-loading\">Loading&hellip;</div>}\n <div className=\"fastboard-view\" ref={useWhiteboard} />\n {toolbar && (\n <div className=\"fastboard-left\">\n <Toolbar {...props} />\n </div>\n )}\n {(redo_undo || zoom_control) && (\n <div className=\"fastboard-bottom-left\">\n {redo_undo && <RedoUndo {...props} />}\n {zoom_control && <ZoomControl {...props} />}\n </div>\n )}\n {page_control && (\n <div className=\"fastboard-bottom-right\">\n <PageControl {...props} />\n </div>\n )}\n </div>\n </Instance.Context.Provider>\n );\n}\n","import type { Mutable } from \"type-fest\";\nimport type { WindowManager } from \"@netless/window-manager\";\nimport type { Room, SceneDefinition, WhiteWebSdk } from \"white-web-sdk\";\nimport type { JoinRoom, ManagerConfig, SdkConfig } from \"./mount-whiteboard\";\nimport type { i18n } from \"i18next\";\n\nimport React, { createContext, useContext } from \"react\";\nimport ReactDOM from \"react-dom\";\n\nimport { Root } from \"../components/Root\";\nimport { mountWhiteboard } from \"./mount-whiteboard\";\nimport { noop } from \"./helpers\";\n\nexport interface AcceptParams {\n readonly sdk: WhiteWebSdk;\n readonly room: Room;\n readonly manager: WindowManager;\n readonly i18n: i18n;\n}\n\nexport interface InsertDocsStatic {\n readonly fileType: \"pdf\" | \"ppt\";\n readonly scenePath: string;\n readonly scenes: SceneDefinition[];\n readonly title?: string;\n}\n\nexport interface InsertDocsDynamic {\n readonly fileType: \"pptx\";\n readonly scenePath: string;\n readonly taskId: string;\n readonly title?: string;\n readonly url?: string;\n}\n\nexport type InsertDocsParams = InsertDocsStatic | InsertDocsDynamic;\n\nexport type Language = \"zh-CN\" | \"en-US\";\n\nexport interface Layout {\n Toolbar?: boolean;\n PageControl?: boolean;\n RedoUndo?: boolean;\n ZoomControl?: boolean;\n}\n\nexport interface WhiteboardAppConfig {\n readonly sdkConfig: SdkConfig;\n readonly joinRoom: JoinRoom;\n readonly managerConfig?: Omit<ManagerConfig, \"container\">;\n readonly layout?: Layout;\n readonly toolbar?: {\n apps?: {\n enable?: boolean;\n content?: React.ReactNode;\n onClick?: () => void;\n };\n };\n readonly language?: Language;\n}\n\nexport interface Essentials {\n readonly sdk: WhiteWebSdk;\n readonly room: Room;\n readonly manager: WindowManager;\n readonly i18n: i18n;\n}\n\nexport class Instance {\n static readonly Context = createContext<Instance | null>(null);\n\n config: Mutable<WhiteboardAppConfig>;\n\n sdk: WhiteWebSdk | null = null;\n room: Room | null = null;\n manager: WindowManager | null = null;\n i18n: i18n | null = null;\n\n ready = false;\n resolveReady!: () => void;\n readyPromise!: Promise<void>;\n\n refreshReadyPromise() {\n this.readyPromise = new Promise<void>(resolve => {\n this.resolveReady = () => {\n this.resolveReady = noop;\n this.ready = true;\n resolve();\n };\n });\n }\n\n constructor(config: WhiteboardAppConfig) {\n this.config = { ...config };\n this.refreshReadyPromise();\n this.initialize();\n }\n\n async initialize() {\n const essentials = await mountWhiteboard(\n this.config.sdkConfig,\n this.config.joinRoom,\n this.config.managerConfig || {},\n this.config.language || \"en-US\"\n );\n this.accept(essentials);\n this.resolveReady();\n }\n\n target: HTMLElement | null = null;\n collector: HTMLElement | null = null;\n\n bindElement(target: HTMLElement | null, collector: HTMLElement | null) {\n if (this.target && target) {\n ReactDOM.unmountComponentAtNode(this.target);\n }\n this.target = target;\n this.collector = collector;\n this.forceUpdate();\n }\n\n updateLayout(layout: Layout | undefined) {\n this.config.layout = layout;\n this.forceUpdate();\n }\n\n async forceUpdate() {\n await this.readyPromise;\n if (this.target) {\n ReactDOM.render(<Root instance={this} />, this.target);\n }\n }\n\n accept({ sdk, room, manager, i18n }: AcceptParams) {\n this.sdk = sdk;\n this.room = room;\n this.manager = manager;\n this.i18n = i18n;\n this.forceUpdate();\n }\n\n async dispose() {\n if (this.room) {\n await this.unmount();\n }\n if (this.target) {\n ReactDOM.unmountComponentAtNode(this.target);\n this.sdk = this.room = this.manager = this.target = null;\n }\n }\n\n async mount(node: HTMLElement) {\n await this.readyPromise;\n if (!this.manager) {\n throw new Error(`[WhiteboardApp] mounted, but not found window manager`);\n }\n if (this.collector) {\n this.manager.bindContainer(node, this.collector);\n } else {\n this.manager.bindContainer(node);\n }\n }\n\n async unmount() {\n if (this.manager) {\n this.manager.destroy();\n this.manager = null;\n }\n if (this.room) {\n try {\n await this.room.disconnect();\n } catch {\n // ignore any error on disconnecting\n }\n this.room = null;\n }\n this.refreshReadyPromise();\n }\n\n insertDocs(params: InsertDocsParams) {\n if (!this.manager) {\n throw new Error(`[WhiteboardApp] cannot insert doc before mounted`);\n }\n switch (params.fileType) {\n case \"pdf\":\n case \"ppt\":\n return this.manager.addApp({\n kind: \"DocsViewer\",\n options: {\n scenePath: params.scenePath,\n title: params.title,\n scenes: params.scenes,\n },\n });\n case \"pptx\":\n return this.manager.addApp({\n kind: \"Slide\",\n options: {\n scenePath: params.scenePath,\n title: params.title,\n },\n attributes: {\n taskId: params.taskId,\n url: params.url,\n },\n });\n }\n }\n\n insertCodeEditor() {\n if (!this.manager) {\n throw new Error(`[WhiteboardApp] cannot insert app before mounted`);\n }\n return this.manager.addApp({\n kind: \"Monaco\",\n options: { title: \"Code Editor\" },\n });\n }\n\n insertGeoGebra() {\n if (!this.manager) {\n throw new Error(`[WhiteboardApp] cannot insert app before mounted`);\n }\n return this.manager.addApp({\n kind: \"GeoGebra\",\n options: { title: \"GeoGebra\" },\n });\n }\n\n insertCountdown() {\n if (!this.manager) {\n throw new Error(`[WhiteboardApp] cannot insert app before mounted`);\n }\n return this.manager.addApp({\n kind: \"Countdown\",\n options: { title: \"Countdown\" },\n });\n }\n\n async changeLanguage(language: Language) {\n try {\n await this.i18n?.changeLanguage(language);\n } finally {\n await this.forceUpdate();\n }\n }\n}\n\nexport function useInstance() {\n return useContext(Instance.Context);\n}\n","import { applyStyles } from \"../internal\";\nimport style from \"../style.scss?inline\";\n\nconst newEl = applyStyles(style);\n\nif (import.meta.hot) {\n import.meta.hot.dispose(data => {\n data.el = newEl;\n });\n import.meta.hot.accept(() => {\n const oldEl = import.meta.hot?.data.el;\n if (oldEl) {\n oldEl.innerText = newEl.innerText;\n newEl.remove();\n }\n });\n}\n","import type {\n InsertDocsParams,\n Language,\n Layout,\n WhiteboardAppConfig,\n} from \"./internal\";\nimport { Instance } from \"./internal\";\n\nexport type { Language, Layout, WhiteboardAppConfig, InsertDocsParams };\n\nexport class WhiteboardApp {\n private readonly _instance: Instance;\n\n constructor(readonly config: WhiteboardAppConfig) {\n this._instance = new Instance(config);\n }\n\n get room() {\n return this._instance.room;\n }\n\n get manager() {\n return this._instance.manager;\n }\n\n get sdk() {\n return this._instance.sdk;\n }\n\n get i18n() {\n return this._instance.i18n;\n }\n\n public get target(): HTMLElement | null {\n return this._instance.target;\n }\n\n public get collector(): HTMLElement | null {\n return this._instance.collector;\n }\n\n public bindElement(\n target?: HTMLElement | null,\n collector?: HTMLElement | null\n ) {\n this._instance.bindElement(target || null, collector || null);\n }\n\n public get layout() {\n return this._instance.config.layout;\n }\n\n public updateLayout(layout?: Layout | undefined) {\n this._instance.updateLayout(layout);\n }\n\n public insertDocs(params: InsertDocsParams) {\n return this._instance.insertDocs(params);\n }\n\n public insertCodeEditor() {\n return this._instance.insertCodeEditor();\n }\n\n public insertGeoGebra() {\n return this._instance.insertGeoGebra();\n }\n\n public insertCountdown() {\n return this._instance.insertCountdown();\n }\n\n public changeLanguage(language: Language) {\n return this._instance.changeLanguage(language);\n }\n\n public dispose() {\n return this._instance.dispose();\n }\n}\n","import type { DependencyList } from \"react\";\nimport type { Player } from \"white-web-sdk\";\n\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport { PlayerPhase } from \"white-web-sdk\";\n\nconst EMPTY_ARRAY: DependencyList = [];\n\nfunction useForceUpdate() {\n const [, forceUpdate_] = useState({});\n // eslint-disable-next-line react-hooks/exhaustive-deps\n return useCallback(() => forceUpdate_({}), EMPTY_ARRAY);\n}\n\nfunction useLastValue<T>(value: T) {\n const ref = useRef<T>(value);\n useEffect(() => {\n ref.current = value;\n }, [value]);\n return ref.current;\n}\n\nexport function usePlayer(player?: Player | null) {\n const togglePlay = useCallback(() => {\n if (player) {\n switch (player.phase) {\n case PlayerPhase.WaitingFirstFrame:\n case PlayerPhase.Pause:\n case PlayerPhase.Ended: {\n player.play();\n break;\n }\n case PlayerPhase.Playing: {\n player.pause();\n break;\n }\n }\n }\n }, [player]);\n\n const seekToProgressTime = useCallback(\n (time: number) => {\n if (player) {\n player.seekToProgressTime(time);\n }\n },\n [player]\n );\n\n const lastPlayer = useLastValue(player);\n\n const forceUpdate = useForceUpdate();\n\n const setSpeed = useCallback(\n (speed: number) => {\n if (player) {\n player.playbackSpeed = speed;\n forceUpdate();\n }\n },\n [forceUpdate, player]\n );\n\n useEffect(() => {\n if (!lastPlayer && player) {\n forceUpdate();\n }\n }, [forceUpdate, lastPlayer, player]);\n\n useEffect(() => {\n if (player) {\n player.callbacks.on(\"onPhaseChanged\", forceUpdate);\n player.callbacks.on(\"onProgressTimeChanged\", forceUpdate);\n return () => {\n player.callbacks.off(\"onPhaseChanged\", forceUpdate);\n player.callbacks.off(\"onProgressTimeChanged\", forceUpdate);\n };\n }\n }, [forceUpdate, player]);\n\n const phase = player ? player.phase : PlayerPhase.WaitingFirstFrame;\n const currentTime = player ? player.progressTime : 0;\n const totalTime = player ? player.timeDuration : 0;\n const speed = player ? player.playbackSpeed : 1;\n\n return {\n phase,\n currentTime,\n totalTime,\n speed,\n setSpeed,\n togglePlay,\n seekToProgressTime,\n };\n}\n","import type { IconProps } from \"../../../types\";\n\nimport React from \"react\";\nimport { getStroke } from \"../../../theme\";\n\nexport const Loading = (props: IconProps) => {\n const stroke = getStroke(props);\n return (\n <svg viewBox=\"0 0 24 24\">\n <path d=\"M12 4V2A10 10 0 0 0 2 12h2a8 8 0 0 1 8-8z\" fill={stroke}></path>\n </svg>\n );\n};\n","import type { IconProps } from \"../../../types\";\n\nimport React from \"react\";\nimport { getStroke } from \"../../../theme\";\n\nexport const Pause = (props: IconProps) => {\n const stroke = getStroke(props);\n return (\n <svg viewBox=\"0 0 24 24\">\n <path d=\"M14 19h4V5h-4M6 19h4V5H6v14z\" fill={stroke}></path>\n </svg>\n );\n};\n","import type { IconProps } from \"../../../types\";\n\nimport React from \"react\";\nimport { getStroke } from \"../../../theme\";\n\nexport const Play = (props: IconProps) => {\n const stroke = getStroke(props);\n return (\n <svg viewBox=\"0 0 24 24\">\n <path d=\"M8 5.14v14l11-7l-11-7z\" fill={stroke}></path>\n </svg>\n );\n};\n","import { memo } from \"react\";\nimport { Loading } from \"./Loading\";\nimport { Pause } from \"./Pause\";\nimport { Play } from \"./Play\";\n\nexport const Icons = {\n Play: memo(Play),\n Pause: memo(Pause),\n Loading: memo(Loading),\n};\n","import type { Placement } from \"tippy.js\";\nimport type { Theme } from \"../../../types\";\n\nimport clsx from \"clsx\";\nimport React, { forwardRef, type PropsWithChildren } from \"react\";\nimport Tippy from \"@tippyjs/react\";\n\nimport { TopOffset } from \"../../../theme\";\n\ntype ButtonProps = PropsWithChildren<{\n theme: Theme;\n content: React.ReactNode;\n disabled?: boolean;\n active?: boolean;\n onClick?: () => void;\n interactive?: boolean;\n placement?: Placement;\n}>;\n\nexport const Button = forwardRef<HTMLButtonElement, ButtonProps>(\n (props, ref) => {\n const {\n theme,\n content,\n disabled,\n active,\n onClick,\n interactive,\n placement = \"top\",\n children,\n } = props;\n\n return (\n <Tippy\n className=\"fastboard-tip\"\n content={content}\n interactive={interactive}\n theme={theme}\n disabled={disabled}\n placement={placement}\n offset={TopOffset}\n duration={300}\n >\n <button\n ref={ref}\n className={clsx(\"fastboard-player-control-btn\", theme, { active })}\n onClick={onClick}\n disabled={disabled}\n >\n {children}\n </button>\n </Tippy>\n );\n }\n);\n","import type { Player } from \"white-web-sdk\";\nimport type { CommonProps, GenericIcon } from \"../../types\";\n\nimport clsx from \"clsx\";\nimport React, { useEffect, useState } from \"react\";\nimport RcSlider from \"rc-slider\";\nimport { PlayerPhase } from \"white-web-sdk\";\nimport { usePlayer } from \"./hooks\";\nimport { Icon } from \"../../icons\";\nimport { themes, TopOffset } from \"../../theme\";\nimport { Icons } from \"./icons\";\nimport Tippy from \"@tippyjs/react\";\nimport { Button } from \"./components/Button\";\n\nexport type PlayerControlProps = {\n autoHide?: boolean;\n player?: Player;\n} & Omit<CommonProps, \"room\"> &\n GenericIcon<\"play\" | \"pause\" | \"loading\">;\n\nexport const name = \"fastboard-player-control\";\n\nexport function PlayerControl({\n autoHide = false,\n player: player_,\n theme = \"light\",\n i18n,\n ...icons\n}: PlayerControlProps) {\n const [currentTime, setCurrentTime] = useState(0);\n const player = usePlayer(player_);\n\n useEffect(() => {\n setCurrentTime(player.currentTime);\n }, [player.currentTime]);\n\n useEffect(() => {\n if (player.currentTime !== currentTime) {\n player.seekToProgressTime(currentTime);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [currentTime]);\n\n const isLoading =\n player.phase === PlayerPhase.WaitingFirstFrame ||\n player.phase === PlayerPhase.Buffering;\n const isPlaying = player.phase === PlayerPhase.Playing;\n\n const { activeColor } = themes[theme];\n\n return (\n <div className={clsx(name, theme, { \"auto-hide\": autoHide })}>\n <button\n className={clsx(\n `${name}-btn`,\n isLoading ? \"loading\" : isPlaying ? \"pause\" : \"play\",\n theme\n )}\n disabled={isLoading}\n onClick={player.togglePlay}\n >\n <Icon\n fallback={\n isLoading ? (\n <Icons.Loading theme={theme} />\n ) : isPlaying ? (\n <Icons.Pause theme={theme} />\n ) : (\n <Icons.Play theme={theme} />\n )\n }\n src={\n isLoading\n ? icons.loadingIcon\n : isPlaying\n ? icons.pauseIcon\n : icons.playIcon\n }\n alt={isLoading ? \"[loading]\" : isPlaying ? \"[pause]\" : \"[play]\"}\n />\n </button>\n <span className={clsx(`${name}-slider`, { loading: isLoading }, theme)}>\n <RcSlider\n disabled={isLoading}\n trackStyle={{ background: activeColor }}\n handleStyle={{ border: `1px solid ${activeColor}` }}\n value={currentTime}\n onChange={setCurrentTime}\n min={0}\n max={player.totalTime}\n step={100}\n />\n </span>\n <span className={clsx(`${name}-current`, theme)}>\n {renderTime(player.currentTime)}\n </span>\n <span className={clsx(`${name}-slash`, theme)}>/</span>\n <span className={clsx(`${name}-total`, theme)}>\n {renderTime(player.totalTime)}\n </span>\n <span className={`${name}-btn-interactive`}>\n <Tippy\n className=\"fastboard-tip\"\n content={renderSpeeds(player)}\n theme={theme}\n placement=\"top-end\"\n trigger=\"click\"\n offset={TopOffset}\n arrow={false}\n interactive\n >\n <Button content={i18n?.t(\"speed\")} theme={theme} disabled={isLoading}>\n <span className={clsx(`${name}-speed-text`, theme)}>\n {player.speed}x\n </span>\n </Button>\n </Tippy>\n </span>\n </div>\n );\n}\n\nfunction renderTime(ms: number) {\n let seconds = ms / 1000;\n const minutes = Math.floor(seconds / 60);\n seconds = Math.floor(seconds) % 60;\n\n return (\n `${String(minutes).padStart(2, \"0\")}` +\n `:${String(seconds).padStart(2, \"0\")}`\n );\n}\n\nconst Speeds = [2.0, 1.5, 1.25, 1.0, 0.75, 0.5];\n\nfunction renderSpeeds({\n speed: current,\n setSpeed,\n}: {\n speed: number;\n setSpeed: (speed: number) => void;\n}) {\n return (\n <div className={clsx(`${name}-panel`, \"speed\")}>\n {Speeds.map(speed => (\n <button\n className={clsx(`${name}-btn`, \"speed\", {\n active: speed === current,\n })}\n key={speed}\n onClick={() => setSpeed(speed)}\n >\n {speed}x\n </button>\n ))}\n </div>\n );\n}\n","import type { WhiteboardApp, WhiteboardAppConfig } from \"./WhiteboardApp\";\n\nimport { useEffect, useState } from \"react\";\nimport { createWhiteboardApp } from \"./index\";\n\nexport type FastBoardConfig = WhiteboardAppConfig;\n\n/**\n * @example\n * const [app, ref] = useFastboard({ sdkConfig, joinRoom })\n * if (app) {\n * app.insertDocs({...})\n * }\n * return <div style={{ width: '100%', height: '100%' }} ref={ref} />\n */\nexport function useFastboard(config: FastBoardConfig): readonly [\n app: WhiteboardApp | null,\n ref: (div: HTMLDivElement | null) => void,\n collectorRef: (div: HTMLDivElement | null) => void\n] & {\n readonly app: WhiteboardApp | null;\n readonly ref: (div: HTMLDivElement | null) => void;\n readonly collectorRef: (div: HTMLDivElement | null) => void;\n} {\n const [app, setApp] = useState<WhiteboardApp | null>(null);\n const [currentTarget, ref] = useState<HTMLDivElement | null>(null);\n const [collector, collectorRef] = useState<HTMLDivElement | null>(null);\n\n useEffect(() => {\n let isMounted = true;\n const promise = createWhiteboardApp(config).then(app => {\n if (isMounted) setApp(app);\n });\n return () => {\n isMounted = false;\n promise.then(() => app?.dispose());\n };\n // ignore config and app change\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n useEffect(() => {\n if (app) {\n app.bindElement(currentTarget, collector);\n }\n }, [app, collector, currentTarget]);\n\n return Object.assign([app, ref, collectorRef] as const, {\n app,\n ref,\n collectorRef,\n });\n}\n","import { WindowManager } from \"@netless/window-manager\";\n\nimport \"./behaviors/register-apps\";\nimport \"./behaviors/style\";\n\nimport { WhiteboardApp, type WhiteboardAppConfig } from \"./WhiteboardApp\";\n\nexport { version } from \"../package.json\";\nexport { PageControl, type PageControlProps } from \"./components/PageControl\";\nexport { RedoUndo, type RedoUndoProps } from \"./components/RedoUndo\";\nexport { Toolbar, type ToolbarProps } from \"./components/Toolbar\";\nexport { ZoomControl, type ZoomControlProps } from \"./components/ZoomControl\";\nexport {\n PlayerControl,\n type PlayerControlProps,\n} from \"./components/PlayerControl\";\nexport * from \"./WhiteboardApp\";\nexport * from \"./hooks\";\n\nexport const register = WindowManager.register.bind(WindowManager);\n\n/**\n * @example\n * let app = await createWhiteboardApp(config)\n * app.bindElement(el)\n */\nexport async function createWhiteboardApp(\n config: WhiteboardAppConfig\n): Promise<WhiteboardApp> {\n const app = new WhiteboardApp(config);\n // @ts-expect-error // eslint-disable-line\n await app._instance.readyPromise;\n return app;\n}\n"],"names":["WindowManager","i18next","WhiteWebSdk","DefaultHotKeys","require$$0","jsxRuntimeModule","jsxRuntime.jsx","jsxRuntime.jsxs","jsxRuntime.Fragment","fallback","src","alt","Apps","props","stroke","getStroke","Arrow","Circle","Clean","Clicker","Collapse","Diamond","Down","Eraser","Expand","Line","Pencil","Rectangle","Selector","SpeechBalloon","Star","Text","Triangle","Up","Icons","memo","Button","forwardRef","ref","content","disabled","active","onClick","interactive","placement","children","writable","theme","useContext","ToolbarContext","Tippy","includes","RightOffset","undefined","clsx","name","useState","useCallback","ApplianceNames","ShapeType","scrollTo","icons","scrollUp","ItemHeight","upIconDisable","upIcon","scrollDown","downIconDisable","downIcon","text","hotkey","toUpperCase","app","useInstance","setAppliance","memberState","i18n","changeAppliance","clicker","shortcut","config","joinRoom","hotKeys","changeToClick","appliance","currentApplianceName","renderToolTip","t","clickerIconDisable","clickerIcon","selector","defaultHotKeys","changeToSelector","selectorIconDisable","selectorIcon","eraser","changeToEraser","eraserIconDisable","eraserIcon","cleanCurrentScene","cleanIconDisable","cleanIcon","button","appsIconDisable","appsIcon","renderAppsButtonContent","vscodePNG","insertCodeEditor","bind","geogebraPNG","insertGeoGebra","countdownPNG","insertCountdown","title","colors","colorKeys","Object","keys","setStrokeColor","strokeColor","map","key","isEqualArray","background","ev","stopPropagation","setStrokeWidth","activeColor","themes","strokeWidth","RcSlider","border","pencil","changeToPencil","renderPencilButtonContent","pencilIconDisable","pencilIcon","changeToText","renderTextButtonContent","textIconDisable","textIcon","ShapeTypes","Set","ApplianceShapes","Shapes","shape","shapeType","has","CurrentIcon","ShapesMap","renderShapesButtonContent","Appliance","Icon","current","useRef","scrollTop","setScrollTop","parentHeight","setParentHeight","hasAppButton","toolbar","apps","enable","needScroll","ItemsCount","sectionHeight","clamp","MinHeight","MaxHeight","scrollBuffer","Math","max","disableScrollUp","disableScrollDown","height","container","parentElement","paddingTop","paddingBottom","getComputedStyle","padding","parseInt","resizeObserver","ResizeObserver","getBoundingClientRect","observe","disconnect","overflow","createContext","EmptyToolbarHook","Toolbar","room","expanded","setExpanded","hook","useToolbar","toggle","e","collapseIconDisable","collapseIcon","expandIconDisable","expandIcon","color","undoIcon","undoIconDisable","redoIcon","redoIconDisable","setWritable","undoSteps","setUndoSteps","redoSteps","setRedoSteps","isWritable","disableSerialization","updateWritable","callbacks","on","off","TopOffset","undo","redo","ScalePoints","scale","delta","length","last","i","curr","prev","next","Infinity","manager","resetIcon","resetIconDisable","minusIcon","minusIconDisable","plusIcon","plusIconDisable","setScale","resetCamera","mainView","moveCamera","centerX","centerY","scenes","index","state","sceneState","ppt","scalePptToFit","zoomIn","nextScale","zoomOut","cameraState","camera","onRoomStateChanged","modifyState","onCameraUpdated","ceil","addIcon","addIconDisable","prevIcon","prevIconDisable","nextIcon","nextIconDisable","pageIndex","setPageIndex","pageCount","setPageCount","addPage","switchMainViewToWriter","path","contextPath","putScenes","setMainViewSceneIndex","setSceneIndex","prevPage","pptPreviousStep","nextPage","pptNextStep","onMainViewModeChanged","mode","instance","mux","Lock","useWhiteboard","schedule","mount","unmount","RedoUndo","redo_undo","ZoomControl","zoom_control","PageControl","page_control","layout","constructor","sdk","ready","resolveReady","readyPromise","target","collector","refreshReadyPromise","initialize","Promise","resolve","noop","essentials","mountWhiteboard","sdkConfig","managerConfig","language","accept","bindElement","unmountComponentAtNode","forceUpdate","updateLayout","render","dispose","node","Error","bindContainer","destroy","insertDocs","params","fileType","addApp","kind","options","scenePath","attributes","taskId","url","changeLanguage","Context","Instance","PlayerPhase","Loading","Pause","Play","autoHide","player","player_","currentTime","setCurrentTime","usePlayer","seekToProgressTime","isLoading","phase","WaitingFirstFrame","Buffering","isPlaying","Playing","togglePlay","loadingIcon","pauseIcon","playIcon","loading","totalTime","renderTime","renderSpeeds","speed","ms","seconds","minutes","floor","String","padStart","Speeds","setSpeed"],"mappings":"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"}