@activecollab/components 2.0.451 → 2.0.452

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.
Files changed (26) hide show
  1. package/dist/cjs/presentation/whiteboard/elements.js +146 -191
  2. package/dist/cjs/presentation/whiteboard/elements.js.map +1 -1
  3. package/dist/cjs/presentation/whiteboard/entityCardActions.js +4 -1
  4. package/dist/cjs/presentation/whiteboard/entityCardActions.js.map +1 -1
  5. package/dist/cjs/presentation/whiteboard/fileElement.js +2 -2
  6. package/dist/cjs/presentation/whiteboard/fileElement.js.map +1 -1
  7. package/dist/cjs/presentation/whiteboard/inspector.js +2 -2
  8. package/dist/cjs/presentation/whiteboard/inspector.js.map +1 -1
  9. package/dist/esm/presentation/whiteboard/elements.d.ts +5 -19
  10. package/dist/esm/presentation/whiteboard/elements.d.ts.map +1 -1
  11. package/dist/esm/presentation/whiteboard/elements.js +129 -168
  12. package/dist/esm/presentation/whiteboard/elements.js.map +1 -1
  13. package/dist/esm/presentation/whiteboard/entityCardActions.d.ts.map +1 -1
  14. package/dist/esm/presentation/whiteboard/entityCardActions.js +4 -1
  15. package/dist/esm/presentation/whiteboard/entityCardActions.js.map +1 -1
  16. package/dist/esm/presentation/whiteboard/fileElement.js +3 -3
  17. package/dist/esm/presentation/whiteboard/fileElement.js.map +1 -1
  18. package/dist/esm/presentation/whiteboard/inspector.js +3 -3
  19. package/dist/esm/presentation/whiteboard/inspector.js.map +1 -1
  20. package/package.json +1 -1
  21. package/dist/cjs/presentation/whiteboard/glyphs.js +0 -67
  22. package/dist/cjs/presentation/whiteboard/glyphs.js.map +0 -1
  23. package/dist/esm/presentation/whiteboard/glyphs.d.ts +0 -32
  24. package/dist/esm/presentation/whiteboard/glyphs.d.ts.map +0 -1
  25. package/dist/esm/presentation/whiteboard/glyphs.js +0 -50
  26. package/dist/esm/presentation/whiteboard/glyphs.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"elements.js","names":["React","useState","styled","MinusGlyph","PlusGlyph","SquareGlyph","Dot","IconButton","ArrowRefreshIcon","CircleIcon","CircleSlashIcon","LockIcon","RoundedRectangleIcon","TextAlignCenterIcon","TextAlignJustifyIcon","TextAlignLeftIcon","TextAlignRightIcon","TextStyleBoldIcon","TextStyleItalicIcon","TextStyleStrikeIcon","TextStyleUnderlineIcon","TrashIcon","TriangleIcon","List","ListItem","Menu","Tooltip","colors","ELEMENT_FILL","ELEMENT_STROKE","ELEMENT_TEXT","STICKY_FILL","SELECTION_BLUE","COLOR_PALETTE","FONT_SIZE_OPTIONS","THICKNESS_OPTIONS","OPACITY_OPTIONS","RADIUS_OPTIONS","ELEMENT_BODIES","COLOR_OPTIONS","Object","values","map","entry","id","color","name","textColor","defaultShapeState","type","fill","fillOpacity","stroke","strokeOpacity","strokeWidth","strokeDash","undefined","borderRadius","fontSize","bold","italic","underline","strikethrough","align","withOpacity","opacityPct","alpha","startsWith","r","parseInt","slice","g","b","replace","shapeBorder","state","lineStyle","stickyGradient","opacity","main","faded","Math","max","GRID_LEVELS","value","label","dotSpacing","snapStep","gridLevel","_GRID_LEVELS$find","find","level","CANVAS_ELEMENTS","kind","initialType","x","y","width","height","INITIAL_SHAPES","reduce","acc","element","INITIAL_POSITIONS","snapValue","step","round","StyledCanvasLayer","div","withConfig","displayName","componentId","StyledCanvasElement","StyledSticky","StyledHandles","RESIZE_DIRECTIONS","ResizeHandles","createElement","onMouseDown","event","stopPropagation","direction","key","className","StyledFormattingToolbar","StyledToolbarButton","button","StyledToolbarLink","withComponent","StyledFontSizeValue","span","stopClick","SUBMENU_SHADOW","StyledColorPopover","WHEEL_SIZE","WHEEL_RADIUS","StyledColorWheel","ColorWheel","_ref","onColorChange","onClick","rect","currentTarget","getBoundingClientRect","dx","clientX","left","dy","clientY","top","distance","sqrt","angle","atan2","PI","hue","saturation","min","StyledSwatchRow","ColorSwatchRow","_ref2","selectedColor","includeTransparent","onSelect","onAddClick","style","backgroundColor","SHAPE_TYPE_ICON","rectangle","roundedRectangle","circle","triangle","SHAPE_TYPE_OPTIONS","BORDER_STYLE_OPTIONS","ToolbarActions","_ref3","locked","onToggleLock","onDelete","Fragment","title","ShapeTypeMenu","_ref4","onChange","_useState","open","setOpen","onOpen","onClose","position","target","variant","active","padding","tabIndex","option","AlignmentMenu","_ref5","_ALIGN_OPTIONS$find","disabled","_useState2","selected","ALIGN_OPTIONS","icon","ToolbarColorSwatch","_ref6","_useState3","_useState4","wheelOpen","setWheelOpen","isTransparent","current","size","ToolbarTextControls","_ref7","styleFlags","onFontSize","onToggleStyle","onAlign","STYLE_OPTIONS","ShapeFormattingToolbar","_ref8","_element$align","onUpdate","PostitFormattingToolbar","_ref9","_extends","renderShapeBody","def","display","overflow","points","strokeDasharray","border"],"sources":["../../../../src/presentation/whiteboard/elements.tsx"],"sourcesContent":["import React, { ReactElement, useState } from \"react\";\n\nimport styled from \"styled-components\";\n\nimport { MinusGlyph, PlusGlyph, SquareGlyph } from \"./glyphs\";\nimport { Dot } from \"../../components/Dot\";\nimport { IconButton } from \"../../components/IconButton\";\nimport {\n ArrowRefreshIcon,\n CircleIcon,\n CircleSlashIcon,\n LockIcon,\n RoundedRectangleIcon,\n TextAlignCenterIcon,\n TextAlignJustifyIcon,\n TextAlignLeftIcon,\n TextAlignRightIcon,\n TextStyleBoldIcon,\n TextStyleItalicIcon,\n TextStyleStrikeIcon,\n TextStyleUnderlineIcon,\n TrashIcon,\n TriangleIcon,\n} from \"../../components/Icons\";\nimport { List, ListItem } from \"../../components/List\";\nimport { Menu } from \"../../components/Menu\";\nimport { Tooltip } from \"../../components/Tooltip\";\nimport { colors } from \"../../utils/colors\";\n\n/* ------------------------------------------------------------------ */\n/* Canvas elements (1:1 with new-activecollab-front */\n/* src/components/Whiteboards/ — constants.js, ShapeElement.jsx, */\n/* PostitElement.jsx, ResizableWrapper.jsx, ResizeHandles.jsx, */\n/* FormattingToolbarContainer.jsx + the two formatting toolbars) */\n/* ------------------------------------------------------------------ */\n\n/* element colors are canvas DATA (app constants), not theme — hardcoded */\nexport const ELEMENT_FILL = \"#ffffff\";\nexport const ELEMENT_STROKE = \"#374151\";\nexport const ELEMENT_TEXT = \"#1f2937\";\nexport const STICKY_FILL = \"#fbbf24\";\nexport const SELECTION_BLUE = \"#3b82f6\";\n\n/* COLOR_PALETTE from toolbar/colorPalette.js (submenu swatch rows) */\nexport const COLOR_PALETTE = [\n \"#ffffff\",\n \"#3b82f6\",\n \"#ef4444\",\n \"#10b981\",\n \"#f59e0b\",\n \"#8b5cf6\",\n \"#f97316\",\n \"#06b6d4\",\n \"#84cc16\",\n \"#ec4899\",\n \"#6b7280\",\n];\n\n/* Discrete option sets for the right Inspector — mirror the app's fixed\n font-size ladder and the border-thickness steps offered in the toolbar. */\nexport const FONT_SIZE_OPTIONS = [\n 10, 13, 16, 20, 24, 30, 36, 48, 72, 96, 144, 216, 288,\n];\nexport const THICKNESS_OPTIONS = [1, 2, 3, 4, 5];\n\nexport const OPACITY_OPTIONS = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100];\n\n/* Corner radii scaled to the board: shapes are drawn at ~100–300px, so the jump\n from a crisp corner to a pill reads across 0–64px. */\nexport const RADIUS_OPTIONS = [0, 4, 8, 12, 16, 24, 32, 48, 64];\n\n/* Element bodies are HTML, as the API returns them (the `body` field). The\n Inspector renders them read-only; when a body is empty the field is omitted.\n Mock the three cases across the canvas: a short body (shape-rounded, the\n default selection), a long one that scrolls (shape-circle), and none at all\n (shape-triangle / sticky). */\nexport const ELEMENT_BODIES: Record<string, string> = {\n \"shape-rounded\": \"<p>Marks the <strong>Kickoff</strong> phase.</p>\",\n \"shape-circle\":\n \"<p>The <strong>discovery</strong> loop for this initiative.</p><p>We collect signals from support, sales and analytics, then cluster them into themes before committing to a direction.</p><ul><li>Owner: research</li><li>Inputs: interviews, tickets, funnel data</li><li>Output: a prioritised opportunity list</li></ul><p>See the <em>retro notes</em> and last quarter's readout for the full context and prior decisions.</p>\",\n};\n\n/* Named-colour options for the Inspector fill/stroke pickers, built from the\n design system's shared data colours (utils/colors). Shaped for the DS Select\n (id + name + color + textColor) so it renders the standard dot-and-radio menu\n used by the label dialogs. */\nexport const COLOR_OPTIONS = Object.values(colors).map((entry) => ({\n id: entry.color,\n name: entry.name,\n color: entry.color,\n textColor: entry.color,\n}));\n\nexport type ShapeType =\n | \"rectangle\"\n | \"roundedRectangle\"\n | \"circle\"\n | \"triangle\";\n\nexport type TextAlign = \"left\" | \"center\" | \"right\" | \"justify\";\n\n/* per-shape editable state (the app bakes opacity into rgba via\n hexToRgba/parseOpacity; the mock keeps opacity separate and rebuilds\n the color when rendering) */\nexport interface ShapeElementState {\n type: ShapeType;\n fill: string;\n fillOpacity: number;\n stroke: string;\n strokeOpacity: number;\n strokeWidth: number;\n strokeDash?: \"5,5\" | \"2,2\";\n borderRadius: number;\n fontSize: number;\n bold: boolean;\n italic: boolean;\n underline: boolean;\n strikethrough: boolean;\n textColor: string;\n /* Text alignment — surfaced in the Inspector's Text group (the floating\n toolbar does not expose it, so it defaults to left). */\n align?: TextAlign;\n}\n\nexport const defaultShapeState = (type: ShapeType): ShapeElementState => ({\n type,\n fill: ELEMENT_FILL,\n fillOpacity: 100,\n stroke: ELEMENT_STROKE,\n strokeOpacity: 100,\n strokeWidth: 2,\n strokeDash: undefined,\n borderRadius: type === \"roundedRectangle\" ? 12 : 0,\n fontSize: 16,\n bold: false,\n italic: false,\n underline: false,\n strikethrough: false,\n textColor: ELEMENT_TEXT,\n align: \"left\",\n});\n\n/* swatches are 6-digit hex, the color wheel returns hsl(...) */\nexport const withOpacity = (color: string, opacityPct: number): string => {\n if (opacityPct >= 100) {\n return color;\n }\n\n const alpha = opacityPct / 100;\n\n if (color.startsWith(\"#\")) {\n const r = parseInt(color.slice(1, 3), 16);\n const g = parseInt(color.slice(3, 5), 16);\n const b = parseInt(color.slice(5, 7), 16);\n\n return `rgba(${r}, ${g}, ${b}, ${alpha})`;\n }\n\n if (color.startsWith(\"hsl(\")) {\n return color.replace(\"hsl(\", \"hsla(\").replace(\")\", `, ${alpha})`);\n }\n\n return color;\n};\n\n/* getShapeBorder from ShapeElement.jsx */\nexport const shapeBorder = (state: ShapeElementState): string => {\n if (state.strokeWidth === 0) {\n return \"none\";\n }\n\n const lineStyle =\n state.strokeDash === \"5,5\"\n ? \"dashed\"\n : state.strokeDash === \"2,2\"\n ? \"dotted\"\n : \"solid\";\n\n return `${state.strokeWidth}px ${lineStyle} ${withOpacity(\n state.stroke,\n state.strokeOpacity\n )}`;\n};\n\n/* PostitElement gradient: color → same color at ~87% alpha */\nexport const stickyGradient = (color: string, opacity = 100): string => {\n const main = withOpacity(color, opacity);\n const faded = withOpacity(color, Math.max(0, opacity - 13));\n\n return `linear-gradient(135deg, ${main} 0%, ${faded} 100%)`;\n};\n\nexport type GridSize = \"off\" | \"small\" | \"large\";\n\n/* Grid config, aligned to the 8px design-system grid. dotSpacing drives the\n dot layer; snapStep drives snapping — decoupled, so each level snaps finer\n than its dots (Small: 16px dots / 8px snap; Large: 32px dots / 16px snap,\n i.e. dots and half-dots). */\nexport const GRID_LEVELS: {\n value: GridSize;\n label: string;\n dotSpacing: number | null;\n snapStep: number | null;\n}[] = [\n { value: \"off\", label: \"Off\", dotSpacing: null, snapStep: null },\n { value: \"small\", label: \"Small\", dotSpacing: 16, snapStep: 8 },\n { value: \"large\", label: \"Large\", dotSpacing: 32, snapStep: 16 },\n];\n\nexport const gridLevel = (value: GridSize): (typeof GRID_LEVELS)[number] =>\n GRID_LEVELS.find((level) => level.value === value) ?? GRID_LEVELS[0];\n\nexport interface CanvasElementDef {\n id: string;\n kind: \"shape\" | \"sticky\";\n initialType?: ShapeType;\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\n/* default sizes from DEFAULT_SHAPE_SIZES / DEFAULT_STICKY_SIZE; positions are\n board-space pixels (top-left) so dragging can snap to the pixel grid */\nexport const CANVAS_ELEMENTS: CanvasElementDef[] = [\n {\n id: \"shape-circle\",\n kind: \"shape\",\n initialType: \"circle\",\n x: 320,\n y: 180,\n width: 80,\n height: 80,\n },\n {\n id: \"shape-rounded\",\n kind: \"shape\",\n initialType: \"roundedRectangle\",\n x: 560,\n y: 300,\n width: 100,\n height: 60,\n },\n {\n id: \"shape-triangle\",\n kind: \"shape\",\n initialType: \"triangle\",\n x: 820,\n y: 170,\n width: 80,\n height: 80,\n },\n {\n id: \"sticky\",\n kind: \"sticky\",\n x: 430,\n y: 430,\n width: 120,\n height: 120,\n },\n];\n\nexport const INITIAL_SHAPES = CANVAS_ELEMENTS.reduce<\n Record<string, ShapeElementState>\n>((acc, element) => {\n if (element.kind === \"shape\" && element.initialType) {\n acc[element.id] = defaultShapeState(element.initialType);\n }\n\n return acc;\n}, {});\n\nexport const INITIAL_POSITIONS = CANVAS_ELEMENTS.reduce<\n Record<string, { x: number; y: number }>\n>((acc, element) => {\n acc[element.id] = { x: element.x, y: element.y };\n\n return acc;\n}, {});\n\nexport const snapValue = (value: number, step: number | null): number =>\n step ? Math.round(value / step) * step : value;\n\n/* deselect happens on canvas-background click (layer under the bars) */\nexport const StyledCanvasLayer = styled.div`\n position: absolute;\n inset: 0;\n\n /* the Link tool is armed: the next drag draws a card box */\n &.drawing {\n cursor: crosshair;\n }\n`;\n\n/* ResizableWrapper: selected = 2px blue-500 ring @50%, hover = 4px\n blue-400 ring @70% (Tailwind rings are box-shadows) */\nexport const StyledCanvasElement = styled.div`\n position: absolute;\n cursor: move;\n\n &:hover:not(.selected) {\n box-shadow: 0 0 0 4px rgba(96, 165, 250, 0.7);\n }\n\n &.selected {\n box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.5);\n }\n\n /* A StackedCard draws its own ring (from --sc-selection-ring, set on the\n canvas to the board blue), so the wrapper's ring would double it. The card\n is also auto-height: the wrapper sets width only and lets the box grow. */\n &.is-card {\n cursor: grab;\n height: auto;\n\n &:hover:not(.selected),\n &.selected {\n box-shadow: none;\n }\n }\n\n /* fill/border/radius come from the element's editable state (inline) */\n .shape-fill {\n width: 100%;\n height: 100%;\n box-sizing: border-box;\n }\n`;\n\n/* PostitElement: 12px padding, shadow-lg, 1deg tilt that straightens on\n hover, diagonal gradient to ~87% alpha, Comic Sans */\nexport const StyledSticky = styled.div`\n width: 100%;\n height: 100%;\n box-sizing: border-box;\n padding: 12px;\n box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1),\n 0 4px 6px -4px rgba(0, 0, 0, 0.1);\n transform: rotate(1deg);\n transition: transform 200ms;\n font-family: \"Comic Sans MS\", cursive, system-ui, sans-serif;\n line-height: 1.4;\n word-break: break-word;\n white-space: pre-wrap;\n\n ${StyledCanvasElement}:hover & {\n transform: rotate(0deg);\n }\n`;\n\n/* ResizeHandles: 8 12px blue squares w/ 2px white border on the box,\n plus the 24px rotate handle outside the bottom-left corner */\nexport const StyledHandles = styled.div`\n .rh {\n position: absolute;\n width: 12px;\n height: 12px;\n box-sizing: border-box;\n background-color: ${SELECTION_BLUE};\n border: 2px solid #ffffff;\n border-radius: 2px;\n z-index: 10;\n\n &:hover {\n background-color: #2563eb;\n }\n }\n\n .rh-nw {\n top: -6px;\n left: -6px;\n cursor: nw-resize;\n }\n .rh-n {\n top: -6px;\n left: 50%;\n margin-left: -6px;\n cursor: n-resize;\n }\n .rh-ne {\n top: -6px;\n right: -6px;\n cursor: ne-resize;\n }\n .rh-w {\n top: 50%;\n left: -6px;\n margin-top: -6px;\n cursor: w-resize;\n }\n .rh-e {\n top: 50%;\n right: -6px;\n margin-top: -6px;\n cursor: e-resize;\n }\n .rh-sw {\n bottom: -6px;\n left: -6px;\n cursor: sw-resize;\n }\n .rh-s {\n bottom: -6px;\n left: 50%;\n margin-left: -6px;\n cursor: s-resize;\n }\n .rh-se {\n bottom: -6px;\n right: -6px;\n cursor: se-resize;\n }\n\n .rotate-handle {\n position: absolute;\n bottom: -35px;\n left: -35px;\n width: 24px;\n height: 24px;\n box-sizing: border-box;\n display: flex;\n align-items: center;\n justify-content: center;\n background-color: #ffffff;\n border: 2px solid ${SELECTION_BLUE};\n border-radius: 50%;\n cursor: grab;\n z-index: 11;\n\n svg {\n width: 16px;\n height: 16px;\n }\n }\n`;\n\nexport const RESIZE_DIRECTIONS = [\"nw\", \"n\", \"ne\", \"w\", \"e\", \"sw\", \"s\", \"se\"];\n\nexport const ResizeHandles = (): ReactElement => (\n <StyledHandles onMouseDown={(event) => event.stopPropagation()}>\n {RESIZE_DIRECTIONS.map((direction) => (\n <span key={direction} className={`rh rh-${direction}`} />\n ))}\n <span className=\"rotate-handle\">\n <ArrowRefreshIcon fill={SELECTION_BLUE} />\n </span>\n </StyledHandles>\n);\n\n/* FormattingToolbarContainer: Paper paper-2 (bg + 8px radius + shadow,\n no border), 8px padding, 4px gap, centered 10px above the element */\nexport const StyledFormattingToolbar = styled.div`\n position: absolute;\n bottom: calc(100% + 10px);\n left: 50%;\n transform: translateX(-50%);\n display: flex;\n align-items: center;\n gap: 4px;\n padding: 8px;\n border-radius: 8px;\n background-color: var(--page-paper-main);\n box-shadow: var(--shadow-tertiary);\n white-space: nowrap;\n cursor: auto;\n z-index: 20;\n\n .tb-group {\n position: relative;\n display: flex;\n align-items: center;\n gap: 4px;\n padding-right: 8px;\n margin-right: 8px;\n border-right: 1px solid var(--border-primary);\n }\n\n /* submenu/popover anchor around a single trigger */\n .tb-rel {\n position: relative;\n display: inline-flex;\n }\n\n .divider {\n width: 1px;\n height: 20px;\n background-color: var(--border-primary);\n margin: 0 4px;\n flex-shrink: 0;\n }\n`;\n\n/* Button variant=\"option\" (idle) / \"tertiary\" (active), h-8 px-2 gap-1 */\nexport const StyledToolbarButton = styled.button`\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 4px;\n height: 32px;\n box-sizing: border-box;\n padding: 0 8px;\n border: 0;\n border-radius: 8px;\n background-color: transparent;\n color: var(--color-secondary);\n font-family: -apple-system, BlinkMacSystemFont, \"Roboto\", \"Helvetica Neue\",\n Arial, sans-serif;\n font-size: 14px;\n cursor: pointer;\n\n &:hover {\n background-color: var(--color-theme-200);\n }\n\n &.active {\n background-color: var(--color-theme-300);\n }\n\n &.icon-only {\n width: 32px;\n padding: 0;\n }\n\n &:disabled {\n opacity: 0.45;\n cursor: default;\n\n &:hover {\n background-color: transparent;\n }\n }\n\n svg {\n fill: currentColor;\n flex-shrink: 0;\n }\n\n svg.i16 {\n width: 16px;\n height: 16px;\n }\n\n svg.i12 {\n width: 12px;\n height: 12px;\n }\n`;\n\n/* Same chrome as a toolbar button, but an <a> — used where the action is a real\n navigation (Visit). `withComponent` keeps the styles and swaps the element, so\n the props type becomes the anchor's. */\nexport const StyledToolbarLink = styled(StyledToolbarButton.withComponent(\"a\"))`\n text-decoration: none;\n`;\n\n/* font-mono min-w-[24px] text-xs readout between the stepper buttons */\nexport const StyledFontSizeValue = styled.span`\n min-width: 24px;\n text-align: center;\n font-family: ui-monospace, SFMono-Regular, Menlo, monospace;\n font-size: 12px;\n color: var(--color-secondary);\n`;\n\nexport const stopClick = (event: React.MouseEvent): void =>\n event.stopPropagation();\n\n/* Shared drop shadow for the colour swatch popover / colour wheel that the\n compact toolbar swatch trigger opens. */\nexport const SUBMENU_SHADOW =\n \"0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -4px rgba(0, 0, 0, 0.1)\";\n\n/* ColorWheelPopover: beside the submenu (SHAPE_POPOVER_CLASS) or below\n a toolbar trigger (sticky default class) */\nexport const StyledColorPopover = styled.div`\n position: absolute;\n box-sizing: border-box;\n padding: 12px;\n background-color: var(--page-paper-main);\n border: 1px solid var(--border-primary);\n border-radius: 8px;\n box-shadow: ${SUBMENU_SHADOW};\n z-index: 70;\n cursor: auto;\n\n &.beside {\n top: 0;\n left: 100%;\n margin-left: 8px;\n }\n\n &.below {\n top: 40px;\n left: 0;\n }\n`;\n\n/* ImprovedColorWheel: hue = angle from east (atan2), saturation = distance,\n lightness 50 — the canvas wheel replicated with CSS gradients */\nexport const WHEEL_SIZE = 200;\nexport const WHEEL_RADIUS = WHEEL_SIZE / 2 - 5;\n\nexport const StyledColorWheel = styled.button`\n display: block;\n width: ${WHEEL_SIZE}px;\n height: ${WHEEL_SIZE}px;\n padding: 0;\n border: 0;\n border-radius: 50%;\n cursor: crosshair;\n box-shadow: ${SUBMENU_SHADOW};\n background: radial-gradient(\n circle closest-side,\n #ffffff,\n rgba(255, 255, 255, 0)\n ),\n conic-gradient(\n from 90deg,\n #ff0000,\n #ffff00,\n #00ff00,\n #00ffff,\n #0000ff,\n #ff00ff,\n #ff0000\n );\n`;\n\nexport interface ColorWheelProps {\n onColorChange: (color: string) => void;\n}\n\nexport const ColorWheel = ({\n onColorChange,\n}: ColorWheelProps): ReactElement => (\n <StyledColorWheel\n onClick={(event) => {\n const rect = event.currentTarget.getBoundingClientRect();\n const dx = event.clientX - rect.left - WHEEL_SIZE / 2;\n const dy = event.clientY - rect.top - WHEEL_SIZE / 2;\n const distance = Math.sqrt(dx * dx + dy * dy);\n\n if (distance > WHEEL_RADIUS) {\n return;\n }\n\n let angle = Math.atan2(dy, dx);\n\n if (angle < 0) {\n angle += 2 * Math.PI;\n }\n\n const hue = Math.round((angle * 180) / Math.PI);\n const saturation = Math.round(\n Math.min(100, (distance / WHEEL_RADIUS) * 100)\n );\n\n onColorChange(`hsl(${hue}, ${saturation}%, 50%)`);\n }}\n />\n);\n\n/* ColorSwatchRow.jsx: 32px swatches + a \"+\" that opens the color wheel */\nexport const StyledSwatchRow = styled.div`\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n\n .swatch {\n width: 32px;\n height: 32px;\n box-sizing: border-box;\n padding: 0;\n border: 2px solid var(--border-primary);\n border-radius: 4px;\n cursor: pointer;\n\n &:hover {\n border-color: var(--color-theme-500);\n }\n\n &.selected {\n box-shadow: 0 0 0 2px ${SELECTION_BLUE};\n }\n }\n\n .swatch-add {\n display: flex;\n align-items: center;\n justify-content: center;\n background-color: var(--color-theme-200);\n color: var(--color-secondary);\n }\n`;\n\nexport interface ColorSwatchRowProps {\n selectedColor?: string;\n /* Adds a \"Transparent\" swatch (a CircleSlash chip) as the first option. Only\n shape fill opts in — a sticky's colour is its whole point, and text colour\n would render invisibly, so both leave this off. Matches the app's\n `includeTransparent` on the shared ColorPicker. */\n includeTransparent?: boolean;\n onSelect: (color: string) => void;\n onAddClick: () => void;\n}\n\nexport const ColorSwatchRow = ({\n selectedColor,\n includeTransparent,\n onSelect,\n onAddClick,\n}: ColorSwatchRowProps): ReactElement => (\n <StyledSwatchRow>\n {includeTransparent ? (\n <button\n type=\"button\"\n className={\n selectedColor === \"transparent\"\n ? \"swatch swatch-add selected\"\n : \"swatch swatch-add\"\n }\n aria-label=\"Transparent\"\n onClick={() => onSelect(\"transparent\")}\n >\n <CircleSlashIcon width={20} height={20} fill=\"currentColor\" />\n </button>\n ) : null}\n {COLOR_PALETTE.map((color) => (\n <button\n key={color}\n type=\"button\"\n className={selectedColor === color ? \"swatch selected\" : \"swatch\"}\n style={{ backgroundColor: color }}\n onClick={() => onSelect(color)}\n />\n ))}\n <button type=\"button\" className=\"swatch swatch-add\" onClick={onAddClick}>\n <PlusGlyph />\n </button>\n </StyledSwatchRow>\n);\n\nexport const SHAPE_TYPE_ICON: Record<ShapeType, ReactElement> = {\n rectangle: <SquareGlyph />,\n roundedRectangle: <RoundedRectangleIcon className=\"i16\" />,\n circle: <CircleIcon className=\"i16\" />,\n triangle: <TriangleIcon className=\"i16\" />,\n};\n\n/* The four shape types, in the order the shape-type menu lists them. */\nexport const SHAPE_TYPE_OPTIONS: { type: ShapeType; label: string }[] = [\n { type: \"rectangle\", label: \"Rectangle\" },\n { type: \"roundedRectangle\", label: \"Rounded Rectangle\" },\n { type: \"circle\", label: \"Circle\" },\n { type: \"triangle\", label: \"Triangle\" },\n];\n\n/* Stroke pattern options — now only the Inspector's Stroke group renders these\n (the shape floating toolbar no longer edits stroke). Mirrors the app's\n STROKE_PATTERN_OPTIONS dash enum: solid | dashed | dotted. */\nexport const BORDER_STYLE_OPTIONS: {\n value?: ShapeElementState[\"strokeDash\"];\n label: string;\n}[] = [\n { value: undefined, label: \"Solid\" },\n { value: \"5,5\", label: \"Dashed\" },\n { value: \"2,2\", label: \"Dotted\" },\n];\n\n/* ── Shared floating-toolbar controls ───────────────────────────────────────\n The floating toolbars were flattened this session to match the app: compact,\n collapsed controls (single-button dropdowns) with uniform 4px spacing and a\n single hairline separator only before Lock / Delete. These mirror the shared\n controls in the app's Inspector/Controls (ShapeTypeMenu, AlignmentMenu,\n ColorPicker compact, ToolbarActions). */\n\n/* ToolbarActions — the trailing block shared by EVERY floating toolbar:\n separator → Lock → Delete, in the standard control colour (not red). Mirrors\n app `toolbar/ToolbarActions.jsx`. */\nexport interface ToolbarActionsProps {\n locked: boolean;\n onToggleLock: () => void;\n onDelete: () => void;\n}\n\nexport const ToolbarActions = ({\n locked,\n onToggleLock,\n onDelete,\n}: ToolbarActionsProps): ReactElement => (\n <>\n <span className=\"divider\" />\n <Tooltip title={locked ? \"Unlock\" : \"Lock\"}>\n <StyledToolbarButton\n className={locked ? \"icon-only active\" : \"icon-only\"}\n aria-pressed={locked}\n onClick={onToggleLock}\n >\n <LockIcon className=\"i16\" />\n </StyledToolbarButton>\n </Tooltip>\n <Tooltip title=\"Delete\">\n <StyledToolbarButton className=\"icon-only\" onClick={onDelete}>\n <TrashIcon className=\"i16\" />\n </StyledToolbarButton>\n </Tooltip>\n </>\n);\n\n/* ShapeTypeMenu — collapsed shape-type picker: one icon button showing the\n current shape, opening a dropdown of the four types. Modeled on the app's\n ShapeTypeMenu (DS Menu + List). */\nexport interface ToolbarShapeTypeMenuProps {\n value: ShapeType;\n onChange: (type: ShapeType) => void;\n}\n\nexport const ShapeTypeMenu = ({\n value,\n onChange,\n}: ToolbarShapeTypeMenuProps): ReactElement => {\n const [open, setOpen] = useState(false);\n\n return (\n <Menu\n open={open}\n onOpen={() => setOpen(true)}\n onClose={() => setOpen(false)}\n position=\"bottom-start\"\n target={\n <IconButton\n type=\"button\"\n variant=\"text gray\"\n active={open}\n aria-label=\"Shape\"\n >\n {SHAPE_TYPE_ICON[value]}\n </IconButton>\n }\n >\n <List style={{ padding: \"8px 0\" }} tabIndex={-1}>\n {SHAPE_TYPE_OPTIONS.map((option) => (\n <ListItem\n key={option.type}\n aria-label={option.label}\n onClick={() => {\n onChange(option.type);\n setOpen(false);\n }}\n >\n {SHAPE_TYPE_ICON[option.type]}\n {option.label}\n </ListItem>\n ))}\n </List>\n </Menu>\n );\n};\n\n/* AlignmentMenu — collapsed alignment picker (single button + dropdown), the\n compact-toolbar counterpart to the Inspector's expanded four-button row.\n Mirrors the app's AlignmentMenu. */\nexport interface ToolbarAlignmentMenuProps {\n value: TextAlign;\n onChange: (align: TextAlign) => void;\n disabled?: boolean;\n}\n\nexport const AlignmentMenu = ({\n value,\n onChange,\n disabled,\n}: ToolbarAlignmentMenuProps): ReactElement => {\n const [open, setOpen] = useState(false);\n const selected =\n ALIGN_OPTIONS.find((option) => option.value === value) ?? ALIGN_OPTIONS[0];\n\n return (\n <Menu\n open={open}\n onOpen={() => setOpen(true)}\n onClose={() => setOpen(false)}\n position=\"bottom-start\"\n target={\n <IconButton\n type=\"button\"\n variant=\"text gray\"\n active={open}\n disabled={disabled}\n aria-label=\"Alignment\"\n >\n {selected.icon}\n </IconButton>\n }\n >\n <List style={{ padding: \"8px 0\" }} tabIndex={-1}>\n {ALIGN_OPTIONS.map((option) => (\n <ListItem\n key={option.value}\n aria-label={option.label}\n onClick={() => {\n onChange(option.value);\n setOpen(false);\n }}\n >\n {option.icon}\n {option.label}\n </ListItem>\n ))}\n </List>\n </Menu>\n );\n};\n\n/* Compact swatch-only colour trigger: a single dot (or a CircleSlash chip when\n transparent) that opens a swatch popover. The Inspector's ColorPickerField\n keeps the swatch + name; the floating toolbars use this swatch-only variant.\n `includeTransparent` is passed through to the swatch row — shape fill opts\n in, sticky fill and text colour do not. */\nexport interface ToolbarColorSwatchProps {\n value: string;\n includeTransparent?: boolean;\n label: string;\n onChange: (color: string) => void;\n}\n\nexport const ToolbarColorSwatch = ({\n value,\n includeTransparent,\n label,\n onChange,\n}: ToolbarColorSwatchProps): ReactElement => {\n const [open, setOpen] = useState(false);\n const [wheelOpen, setWheelOpen] = useState(false);\n const isTransparent = value === \"transparent\";\n\n return (\n <span className=\"tb-rel\">\n <Tooltip title={label}>\n <StyledToolbarButton\n className={open ? \"icon-only active\" : \"icon-only\"}\n aria-label={label}\n onClick={() => {\n setOpen((current) => !current);\n setWheelOpen(false);\n }}\n >\n {isTransparent ? (\n <CircleSlashIcon width={16} height={16} fill=\"currentColor\" />\n ) : (\n <Dot color={value} size={16} />\n )}\n </StyledToolbarButton>\n </Tooltip>\n {open ? (\n <StyledColorPopover className=\"below\">\n <ColorSwatchRow\n selectedColor={value}\n includeTransparent={includeTransparent}\n onSelect={(color) => {\n onChange(color);\n setOpen(false);\n }}\n onAddClick={() => setWheelOpen((current) => !current)}\n />\n {wheelOpen ? (\n <StyledColorPopover className=\"beside\">\n <ColorWheel\n onColorChange={(color) => {\n onChange(color);\n setOpen(false);\n }}\n />\n </StyledColorPopover>\n ) : null}\n </StyledColorPopover>\n ) : null}\n </span>\n );\n};\n\n/* The text controls shared by the shape and sticky toolbars: font-size stepper,\n B / I / U / S, and the collapsed alignment menu. Same set the app's sticky\n and shape toolbars share (font-size picker, TextStyleButtons, AlignmentMenu).\n Kept generic so both element shapes can drive it. */\nexport interface ToolbarTextControlsProps {\n fontSize: number;\n styleFlags: {\n bold: boolean;\n italic: boolean;\n underline: boolean;\n strikethrough: boolean;\n };\n align: TextAlign;\n onFontSize: (size: number) => void;\n onToggleStyle: (key: TextStyleKey) => void;\n onAlign: (align: TextAlign) => void;\n}\n\nexport const ToolbarTextControls = ({\n fontSize,\n styleFlags,\n align,\n onFontSize,\n onToggleStyle,\n onAlign,\n}: ToolbarTextControlsProps): ReactElement => (\n <>\n <Tooltip title=\"Decrease font size\">\n <StyledToolbarButton\n className=\"icon-only\"\n aria-label=\"Decrease font size\"\n onClick={() => onFontSize(Math.max(8, fontSize - 2))}\n >\n <MinusGlyph className=\"i16\" />\n </StyledToolbarButton>\n </Tooltip>\n <StyledFontSizeValue>{fontSize}</StyledFontSizeValue>\n <Tooltip title=\"Increase font size\">\n <StyledToolbarButton\n className=\"icon-only\"\n aria-label=\"Increase font size\"\n onClick={() => onFontSize(Math.min(96, fontSize + 2))}\n >\n <PlusGlyph className=\"i16\" />\n </StyledToolbarButton>\n </Tooltip>\n {STYLE_OPTIONS.map((option) => (\n <Tooltip key={option.key} title={option.label}>\n <StyledToolbarButton\n className={styleFlags[option.key] ? \"icon-only active\" : \"icon-only\"}\n aria-label={option.label}\n aria-pressed={styleFlags[option.key]}\n onClick={() => onToggleStyle(option.key)}\n >\n {option.icon}\n </StyledToolbarButton>\n </Tooltip>\n ))}\n <AlignmentMenu value={align} onChange={onAlign} />\n </>\n);\n\nexport interface ShapeFormattingToolbarProps {\n element: ShapeElementState;\n onUpdate: (partial: Partial<ShapeElementState>) => void;\n onDelete: () => void;\n locked: boolean;\n onToggleLock: () => void;\n}\n\n/* ShapeFormattingToolbar — flat layout (was submenu-based): shape-type menu →\n fill colour → the same text controls as the sticky toolbar → Lock / Delete.\n Stroke is no longer edited here — it lives only in the Inspector's Stroke\n group now. Mirrors the app's ShapeFormattingToolbar. */\nexport const ShapeFormattingToolbar = ({\n element,\n onUpdate,\n onDelete,\n locked,\n onToggleLock,\n}: ShapeFormattingToolbarProps): ReactElement => (\n <StyledFormattingToolbar onClick={stopClick} onMouseDown={stopClick}>\n <ShapeTypeMenu\n value={element.type}\n onChange={(type) => onUpdate({ type })}\n />\n <ToolbarColorSwatch\n value={element.fill}\n includeTransparent\n label=\"Fill color\"\n onChange={(fill) => onUpdate({ fill })}\n />\n <ToolbarTextControls\n fontSize={element.fontSize}\n styleFlags={element}\n align={element.align ?? \"left\"}\n onFontSize={(fontSize) => onUpdate({ fontSize })}\n onToggleStyle={(key) => onUpdate({ [key]: !element[key] })}\n onAlign={(align) => onUpdate({ align })}\n />\n <ToolbarActions\n locked={locked}\n onToggleLock={onToggleLock}\n onDelete={onDelete}\n />\n </StyledFormattingToolbar>\n);\n\nexport interface StickyTextStyle {\n fontSize: number;\n bold: boolean;\n italic: boolean;\n strikethrough: boolean;\n underline: boolean;\n align: TextAlign;\n textColor: string;\n color: string;\n fillOpacity: number;\n}\n\nexport interface PostitFormattingToolbarProps {\n value: StickyTextStyle;\n onChange: (next: StickyTextStyle) => void;\n onDelete: () => void;\n locked: boolean;\n onToggleLock: () => void;\n}\n\n/* PostitFormattingToolbar — flat layout: note (fill) colour → the shared text\n controls (font-size, B/I/U/S, alignment menu) → Lock / Delete. The note's\n colour is its whole point, so its fill swatch does NOT offer Transparent.\n Mirrors the app's PostitFormattingToolbar. */\nexport const PostitFormattingToolbar = ({\n value,\n onChange,\n onDelete,\n locked,\n onToggleLock,\n}: PostitFormattingToolbarProps): ReactElement => (\n <StyledFormattingToolbar onClick={stopClick} onMouseDown={stopClick}>\n <ToolbarColorSwatch\n value={value.color}\n label=\"Note color\"\n onChange={(color) => onChange({ ...value, color })}\n />\n <ToolbarTextControls\n fontSize={value.fontSize}\n styleFlags={value}\n align={value.align}\n onFontSize={(fontSize) => onChange({ ...value, fontSize })}\n onToggleStyle={(key) => onChange({ ...value, [key]: !value[key] })}\n onAlign={(align) => onChange({ ...value, align })}\n />\n <ToolbarActions\n locked={locked}\n onToggleLock={onToggleLock}\n onDelete={onDelete}\n />\n </StyledFormattingToolbar>\n);\n\n/* shape body per current (editable) type */\nexport const renderShapeBody = (\n def: CanvasElementDef,\n state: ShapeElementState,\n /* Effective size — the Inspector can override the element's default width /\n height, so the triangle polygon is drawn from the live size, not the def. */\n width: number = def.width,\n height: number = def.height\n): ReactElement =>\n state.type === \"triangle\" ? (\n /* TriangleElement: SVG polygon, apex top-center */\n <svg\n width=\"100%\"\n height=\"100%\"\n style={{ display: \"block\", overflow: \"visible\" }}\n >\n <polygon\n points={`${width / 2},0 ${width},${height} 0,${height}`}\n fill={withOpacity(state.fill, state.fillOpacity)}\n stroke={withOpacity(state.stroke, state.strokeOpacity)}\n strokeWidth={state.strokeWidth}\n strokeDasharray={state.strokeDash}\n />\n </svg>\n ) : (\n <div\n className=\"shape-fill\"\n style={{\n backgroundColor: withOpacity(state.fill, state.fillOpacity),\n border: shapeBorder(state),\n borderRadius: state.type === \"circle\" ? \"50%\" : state.borderRadius,\n }}\n />\n );\n\nexport const ALIGN_OPTIONS: {\n value: TextAlign;\n label: string;\n icon: ReactElement;\n}[] = [\n { value: \"left\", label: \"Align Left\", icon: <TextAlignLeftIcon /> },\n { value: \"center\", label: \"Align Center\", icon: <TextAlignCenterIcon /> },\n { value: \"right\", label: \"Align Right\", icon: <TextAlignRightIcon /> },\n { value: \"justify\", label: \"Justify\", icon: <TextAlignJustifyIcon /> },\n];\n\nexport type TextStyleKey = \"bold\" | \"italic\" | \"underline\" | \"strikethrough\";\n\nexport const STYLE_OPTIONS: {\n key: TextStyleKey;\n label: string;\n icon: ReactElement;\n}[] = [\n { key: \"bold\", label: \"Bold\", icon: <TextStyleBoldIcon /> },\n { key: \"italic\", label: \"Italic\", icon: <TextStyleItalicIcon /> },\n { key: \"underline\", label: \"Underline\", icon: <TextStyleUnderlineIcon /> },\n {\n key: \"strikethrough\",\n label: \"Strikethrough\",\n icon: <TextStyleStrikeIcon />,\n },\n];\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"elements.js","names":["React","useState","styled","Dot","IconButton","ArrowRefreshIcon","CircleIcon","CircleSlashIcon","LockIcon","RoundedRectangleIcon","TextAlignCenterIcon","TextAlignJustifyIcon","TextAlignLeftIcon","TextAlignRightIcon","TextStyleBoldIcon","TextStyleItalicIcon","TextStyleStrikeIcon","TextStyleUnderlineIcon","TrashIcon","TriangleIcon","List","ListItem","Menu","Select","SelectTrigger","Tooltip","colors","ELEMENT_FILL","ELEMENT_STROKE","ELEMENT_TEXT","STICKY_FILL","SELECTION_BLUE","FONT_SIZE_OPTIONS","THICKNESS_OPTIONS","OPACITY_OPTIONS","RADIUS_OPTIONS","ELEMENT_BODIES","COLOR_OPTIONS","Object","values","map","entry","id","color","name","textColor","defaultShapeState","type","fill","fillOpacity","stroke","strokeOpacity","strokeWidth","strokeDash","undefined","borderRadius","fontSize","bold","italic","underline","strikethrough","align","withOpacity","opacityPct","alpha","startsWith","r","parseInt","slice","g","b","replace","shapeBorder","state","lineStyle","stickyGradient","opacity","main","faded","Math","max","GRID_LEVELS","value","label","dotSpacing","snapStep","gridLevel","_GRID_LEVELS$find","find","level","CANVAS_ELEMENTS","kind","initialType","x","y","width","height","INITIAL_SHAPES","reduce","acc","element","INITIAL_POSITIONS","snapValue","step","round","StyledCanvasLayer","div","withConfig","displayName","componentId","StyledCanvasElement","StyledSticky","StyledHandles","RESIZE_DIRECTIONS","ResizeHandles","createElement","onMouseDown","event","stopPropagation","direction","key","className","StyledFormattingToolbar","StyledToolbarButton","button","StyledToolbarLink","withComponent","stopClick","TOOLBAR_SELECT_WIDTH","TOOLBAR_COLOR_TRIGGER_WIDTH","RoundedRectangleOutline","span","SHAPE_TYPE_ICON","rectangle","roundedRectangle","circle","triangle","SHAPE_TYPE_OPTIONS","BORDER_STYLE_OPTIONS","ToolbarActions","_ref","locked","onToggleLock","onDelete","Fragment","title","onClick","ShapeTypeMenu","_ref2","onChange","_useState","open","setOpen","onOpen","onClose","position","target","variant","active","style","padding","tabIndex","option","AlignmentMenu","_ref3","_ALIGN_OPTIONS$find","disabled","_useState2","selected","ALIGN_OPTIONS","icon","TOOLBAR_TRANSPARENT_OPTION","sameHex","a","toLowerCase","ColorDot","_ref4","size","ToolbarColorSwatch","_ref5","_options$find$id","_options$find","includeTransparent","options","disableSearch","forceCloseMenu","keepSameOptionsOrder","next","String","Array","isArray","renderOption","paddingLeft","paddingRight","ToolbarFontSizeSelect","_ref6","Number","ToolbarTextControls","_ref7","styleFlags","onFontSize","onToggleStyle","onAlign","STYLE_OPTIONS","ShapeFormattingToolbar","_ref8","_element$align","onUpdate","PostitFormattingToolbar","_ref9","_extends","renderShapeBody","def","display","overflow","points","strokeDasharray","backgroundColor","border"],"sources":["../../../../src/presentation/whiteboard/elements.tsx"],"sourcesContent":["import React, { ReactElement, useState } from \"react\";\n\nimport styled from \"styled-components\";\n\nimport { Dot } from \"../../components/Dot\";\nimport { IconButton } from \"../../components/IconButton\";\nimport {\n ArrowRefreshIcon,\n CircleIcon,\n CircleSlashIcon,\n LockIcon,\n RoundedRectangleIcon,\n TextAlignCenterIcon,\n TextAlignJustifyIcon,\n TextAlignLeftIcon,\n TextAlignRightIcon,\n TextStyleBoldIcon,\n TextStyleItalicIcon,\n TextStyleStrikeIcon,\n TextStyleUnderlineIcon,\n TrashIcon,\n TriangleIcon,\n} from \"../../components/Icons\";\nimport { List, ListItem } from \"../../components/List\";\nimport { Menu } from \"../../components/Menu\";\nimport { Select } from \"../../components/Select\";\nimport { SelectTrigger } from \"../../components/SelectTrigger\";\nimport { Tooltip } from \"../../components/Tooltip\";\nimport { colors } from \"../../utils/colors\";\n\n/* ------------------------------------------------------------------ */\n/* Canvas elements (1:1 with new-activecollab-front */\n/* src/components/Whiteboards/ — constants.js, ShapeElement.jsx, */\n/* PostitElement.jsx, ResizableWrapper.jsx, ResizeHandles.jsx, */\n/* FormattingToolbarContainer.jsx + the two formatting toolbars) */\n/* ------------------------------------------------------------------ */\n\n/* element colors are canvas DATA (app constants), not theme — hardcoded */\nexport const ELEMENT_FILL = \"#ffffff\";\nexport const ELEMENT_STROKE = \"#374151\";\nexport const ELEMENT_TEXT = \"#1f2937\";\nexport const STICKY_FILL = \"#fbbf24\";\nexport const SELECTION_BLUE = \"#3b82f6\";\n\n/* Discrete option sets for the right Inspector — mirror the app's fixed\n font-size ladder and the border-thickness steps offered in the toolbar. */\nexport const FONT_SIZE_OPTIONS = [\n 10, 13, 16, 20, 24, 30, 36, 48, 72, 96, 144, 216, 288,\n];\nexport const THICKNESS_OPTIONS = [1, 2, 3, 4, 5];\n\nexport const OPACITY_OPTIONS = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100];\n\n/* Corner radii scaled to the board: shapes are drawn at ~100–300px, so the jump\n from a crisp corner to a pill reads across 0–64px. */\nexport const RADIUS_OPTIONS = [0, 4, 8, 12, 16, 24, 32, 48, 64];\n\n/* Element bodies are HTML, as the API returns them (the `body` field). The\n Inspector renders them read-only; when a body is empty the field is omitted.\n Mock the three cases across the canvas: a short body (shape-rounded, the\n default selection), a long one that scrolls (shape-circle), and none at all\n (shape-triangle / sticky). */\nexport const ELEMENT_BODIES: Record<string, string> = {\n \"shape-rounded\": \"<p>Marks the <strong>Kickoff</strong> phase.</p>\",\n \"shape-circle\":\n \"<p>The <strong>discovery</strong> loop for this initiative.</p><p>We collect signals from support, sales and analytics, then cluster them into themes before committing to a direction.</p><ul><li>Owner: research</li><li>Inputs: interviews, tickets, funnel data</li><li>Output: a prioritised opportunity list</li></ul><p>See the <em>retro notes</em> and last quarter's readout for the full context and prior decisions.</p>\",\n};\n\n/* Named-colour options for the Inspector fill/stroke pickers, built from the\n design system's shared data colours (utils/colors). Shaped for the DS Select\n (id + name + color + textColor) so it renders the standard dot-and-radio menu\n used by the label dialogs. */\nexport const COLOR_OPTIONS = Object.values(colors).map((entry) => ({\n id: entry.color,\n name: entry.name,\n color: entry.color,\n textColor: entry.color,\n}));\n\nexport type ShapeType =\n | \"rectangle\"\n | \"roundedRectangle\"\n | \"circle\"\n | \"triangle\";\n\nexport type TextAlign = \"left\" | \"center\" | \"right\" | \"justify\";\n\n/* per-shape editable state (the app bakes opacity into rgba via\n hexToRgba/parseOpacity; the mock keeps opacity separate and rebuilds\n the color when rendering) */\nexport interface ShapeElementState {\n type: ShapeType;\n fill: string;\n fillOpacity: number;\n stroke: string;\n strokeOpacity: number;\n strokeWidth: number;\n strokeDash?: \"5,5\" | \"2,2\";\n borderRadius: number;\n fontSize: number;\n bold: boolean;\n italic: boolean;\n underline: boolean;\n strikethrough: boolean;\n textColor: string;\n /* Text alignment — surfaced in the Inspector's Text group (the floating\n toolbar does not expose it, so it defaults to left). */\n align?: TextAlign;\n}\n\nexport const defaultShapeState = (type: ShapeType): ShapeElementState => ({\n type,\n fill: ELEMENT_FILL,\n fillOpacity: 100,\n stroke: ELEMENT_STROKE,\n strokeOpacity: 100,\n strokeWidth: 2,\n strokeDash: undefined,\n borderRadius: type === \"roundedRectangle\" ? 12 : 0,\n fontSize: 16,\n bold: false,\n italic: false,\n underline: false,\n strikethrough: false,\n textColor: ELEMENT_TEXT,\n align: \"left\",\n});\n\n/* swatches are 6-digit hex, the color wheel returns hsl(...) */\nexport const withOpacity = (color: string, opacityPct: number): string => {\n if (opacityPct >= 100) {\n return color;\n }\n\n const alpha = opacityPct / 100;\n\n if (color.startsWith(\"#\")) {\n const r = parseInt(color.slice(1, 3), 16);\n const g = parseInt(color.slice(3, 5), 16);\n const b = parseInt(color.slice(5, 7), 16);\n\n return `rgba(${r}, ${g}, ${b}, ${alpha})`;\n }\n\n if (color.startsWith(\"hsl(\")) {\n return color.replace(\"hsl(\", \"hsla(\").replace(\")\", `, ${alpha})`);\n }\n\n return color;\n};\n\n/* getShapeBorder from ShapeElement.jsx */\nexport const shapeBorder = (state: ShapeElementState): string => {\n if (state.strokeWidth === 0) {\n return \"none\";\n }\n\n const lineStyle =\n state.strokeDash === \"5,5\"\n ? \"dashed\"\n : state.strokeDash === \"2,2\"\n ? \"dotted\"\n : \"solid\";\n\n return `${state.strokeWidth}px ${lineStyle} ${withOpacity(\n state.stroke,\n state.strokeOpacity\n )}`;\n};\n\n/* PostitElement gradient: color → same color at ~87% alpha */\nexport const stickyGradient = (color: string, opacity = 100): string => {\n const main = withOpacity(color, opacity);\n const faded = withOpacity(color, Math.max(0, opacity - 13));\n\n return `linear-gradient(135deg, ${main} 0%, ${faded} 100%)`;\n};\n\nexport type GridSize = \"off\" | \"small\" | \"large\";\n\n/* Grid config, aligned to the 8px design-system grid. dotSpacing drives the\n dot layer; snapStep drives snapping — decoupled, so each level snaps finer\n than its dots (Small: 16px dots / 8px snap; Large: 32px dots / 16px snap,\n i.e. dots and half-dots). */\nexport const GRID_LEVELS: {\n value: GridSize;\n label: string;\n dotSpacing: number | null;\n snapStep: number | null;\n}[] = [\n { value: \"off\", label: \"Off\", dotSpacing: null, snapStep: null },\n { value: \"small\", label: \"Small\", dotSpacing: 16, snapStep: 8 },\n { value: \"large\", label: \"Large\", dotSpacing: 32, snapStep: 16 },\n];\n\nexport const gridLevel = (value: GridSize): (typeof GRID_LEVELS)[number] =>\n GRID_LEVELS.find((level) => level.value === value) ?? GRID_LEVELS[0];\n\nexport interface CanvasElementDef {\n id: string;\n kind: \"shape\" | \"sticky\";\n initialType?: ShapeType;\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\n/* default sizes from DEFAULT_SHAPE_SIZES / DEFAULT_STICKY_SIZE; positions are\n board-space pixels (top-left) so dragging can snap to the pixel grid */\nexport const CANVAS_ELEMENTS: CanvasElementDef[] = [\n {\n id: \"shape-circle\",\n kind: \"shape\",\n initialType: \"circle\",\n x: 320,\n y: 180,\n width: 80,\n height: 80,\n },\n {\n id: \"shape-rounded\",\n kind: \"shape\",\n initialType: \"roundedRectangle\",\n x: 560,\n y: 300,\n width: 100,\n height: 60,\n },\n {\n id: \"shape-triangle\",\n kind: \"shape\",\n initialType: \"triangle\",\n x: 820,\n y: 170,\n width: 80,\n height: 80,\n },\n {\n id: \"sticky\",\n kind: \"sticky\",\n x: 430,\n y: 430,\n width: 120,\n height: 120,\n },\n];\n\nexport const INITIAL_SHAPES = CANVAS_ELEMENTS.reduce<\n Record<string, ShapeElementState>\n>((acc, element) => {\n if (element.kind === \"shape\" && element.initialType) {\n acc[element.id] = defaultShapeState(element.initialType);\n }\n\n return acc;\n}, {});\n\nexport const INITIAL_POSITIONS = CANVAS_ELEMENTS.reduce<\n Record<string, { x: number; y: number }>\n>((acc, element) => {\n acc[element.id] = { x: element.x, y: element.y };\n\n return acc;\n}, {});\n\nexport const snapValue = (value: number, step: number | null): number =>\n step ? Math.round(value / step) * step : value;\n\n/* deselect happens on canvas-background click (layer under the bars) */\nexport const StyledCanvasLayer = styled.div`\n position: absolute;\n inset: 0;\n\n /* the Link tool is armed: the next drag draws a card box */\n &.drawing {\n cursor: crosshair;\n }\n`;\n\n/* ResizableWrapper: selected = 2px blue-500 ring @50%, hover = 4px\n blue-400 ring @70% (Tailwind rings are box-shadows) */\nexport const StyledCanvasElement = styled.div`\n position: absolute;\n cursor: move;\n\n &:hover:not(.selected) {\n box-shadow: 0 0 0 4px rgba(96, 165, 250, 0.7);\n }\n\n &.selected {\n box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.5);\n }\n\n /* A StackedCard draws its own ring (from --sc-selection-ring, set on the\n canvas to the board blue), so the wrapper's ring would double it. The card\n is also auto-height: the wrapper sets width only and lets the box grow. */\n &.is-card {\n cursor: grab;\n height: auto;\n\n &:hover:not(.selected),\n &.selected {\n box-shadow: none;\n }\n }\n\n /* fill/border/radius come from the element's editable state (inline) */\n .shape-fill {\n width: 100%;\n height: 100%;\n box-sizing: border-box;\n }\n`;\n\n/* PostitElement: 12px padding, shadow-lg, 1deg tilt that straightens on\n hover, diagonal gradient to ~87% alpha, Comic Sans */\nexport const StyledSticky = styled.div`\n width: 100%;\n height: 100%;\n box-sizing: border-box;\n padding: 12px;\n box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1),\n 0 4px 6px -4px rgba(0, 0, 0, 0.1);\n transform: rotate(1deg);\n transition: transform 200ms;\n font-family: \"Comic Sans MS\", cursive, system-ui, sans-serif;\n line-height: 1.4;\n word-break: break-word;\n white-space: pre-wrap;\n\n ${StyledCanvasElement}:hover & {\n transform: rotate(0deg);\n }\n`;\n\n/* ResizeHandles: 8 12px blue squares w/ 2px white border on the box,\n plus the 24px rotate handle outside the bottom-left corner */\nexport const StyledHandles = styled.div`\n .rh {\n position: absolute;\n width: 12px;\n height: 12px;\n box-sizing: border-box;\n background-color: ${SELECTION_BLUE};\n border: 2px solid #ffffff;\n border-radius: 2px;\n z-index: 10;\n\n &:hover {\n background-color: #2563eb;\n }\n }\n\n .rh-nw {\n top: -6px;\n left: -6px;\n cursor: nw-resize;\n }\n .rh-n {\n top: -6px;\n left: 50%;\n margin-left: -6px;\n cursor: n-resize;\n }\n .rh-ne {\n top: -6px;\n right: -6px;\n cursor: ne-resize;\n }\n .rh-w {\n top: 50%;\n left: -6px;\n margin-top: -6px;\n cursor: w-resize;\n }\n .rh-e {\n top: 50%;\n right: -6px;\n margin-top: -6px;\n cursor: e-resize;\n }\n .rh-sw {\n bottom: -6px;\n left: -6px;\n cursor: sw-resize;\n }\n .rh-s {\n bottom: -6px;\n left: 50%;\n margin-left: -6px;\n cursor: s-resize;\n }\n .rh-se {\n bottom: -6px;\n right: -6px;\n cursor: se-resize;\n }\n\n .rotate-handle {\n position: absolute;\n bottom: -35px;\n left: -35px;\n width: 24px;\n height: 24px;\n box-sizing: border-box;\n display: flex;\n align-items: center;\n justify-content: center;\n background-color: #ffffff;\n border: 2px solid ${SELECTION_BLUE};\n border-radius: 50%;\n cursor: grab;\n z-index: 11;\n\n svg {\n width: 16px;\n height: 16px;\n }\n }\n`;\n\nexport const RESIZE_DIRECTIONS = [\"nw\", \"n\", \"ne\", \"w\", \"e\", \"sw\", \"s\", \"se\"];\n\nexport const ResizeHandles = (): ReactElement => (\n <StyledHandles onMouseDown={(event) => event.stopPropagation()}>\n {RESIZE_DIRECTIONS.map((direction) => (\n <span key={direction} className={`rh rh-${direction}`} />\n ))}\n <span className=\"rotate-handle\">\n <ArrowRefreshIcon fill={SELECTION_BLUE} />\n </span>\n </StyledHandles>\n);\n\n/* FormattingToolbarContainer: Paper paper-2 (bg + 8px radius + shadow,\n no border), 8px padding, 4px gap, centered 10px above the element */\nexport const StyledFormattingToolbar = styled.div`\n position: absolute;\n bottom: calc(100% + 10px);\n left: 50%;\n transform: translateX(-50%);\n display: flex;\n align-items: center;\n gap: 4px;\n padding: 8px;\n border-radius: 8px;\n background-color: var(--page-paper-main);\n box-shadow: var(--shadow-tertiary);\n white-space: nowrap;\n cursor: auto;\n z-index: 20;\n\n .tb-group {\n position: relative;\n display: flex;\n align-items: center;\n gap: 4px;\n padding-right: 8px;\n margin-right: 8px;\n border-right: 1px solid var(--border-primary);\n }\n\n /* submenu/popover anchor around a single trigger */\n .tb-rel {\n position: relative;\n display: inline-flex;\n }\n\n .tb-color-value {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 100%;\n }\n\n .divider {\n width: 1px;\n height: 20px;\n background-color: var(--border-primary);\n margin: 0 4px;\n flex-shrink: 0;\n }\n`;\n\n/* The app's toolbar buttons are DS `Button` / `IconButton` variant=\"option\",\n size small, h-8 px-2: grey text (theme-700) that darkens on hover over a\n theme-300 wash, and the primary colour only for a PRESSED state (an armed\n lock, an active text style). Same palette here, so the story's bars read as\n the app's and not as a row of links. */\nexport const StyledToolbarButton = styled.button`\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 4px;\n height: 32px;\n box-sizing: border-box;\n padding: 0 8px;\n border: 0;\n border-radius: var(--ac-br-6);\n background-color: transparent;\n color: var(--color-theme-700);\n font-family: -apple-system, BlinkMacSystemFont, \"Roboto\", \"Helvetica Neue\",\n Arial, sans-serif;\n font-size: 14px;\n font-weight: 500;\n cursor: pointer;\n\n &:hover,\n &:focus-visible {\n background-color: var(--color-theme-300);\n color: var(--color-theme-900);\n }\n\n &.active,\n &.active:hover {\n color: var(--color-primary);\n }\n\n &.icon-only {\n width: 32px;\n padding: 0;\n }\n\n &:disabled {\n opacity: 0.45;\n cursor: default;\n\n &:hover {\n background-color: transparent;\n }\n }\n\n svg {\n fill: currentColor;\n flex-shrink: 0;\n }\n\n svg.i16 {\n width: 16px;\n height: 16px;\n }\n\n svg.i12 {\n width: 12px;\n height: 12px;\n }\n`;\n\n/* Same chrome as a toolbar button, but an <a> — used where the action is a real\n navigation (Visit). `withComponent` keeps the styles and swaps the element, so\n the props type becomes the anchor's. */\nexport const StyledToolbarLink = styled(StyledToolbarButton.withComponent(\"a\"))`\n text-decoration: none;\n`;\n\nexport const stopClick = (event: React.MouseEvent): void =>\n event.stopPropagation();\n\n/* The trigger widths the app gives its toolbar selects: `tw-w-20` for the font\n size (\"16 pt\"), `tw-w-16 tw-px-2` for the swatch-only colour trigger. */\nconst TOOLBAR_SELECT_WIDTH = 80;\nconst TOOLBAR_COLOR_TRIGGER_WIDTH = 64;\n\n/* Hollow rounded rectangle, the app's own glyph for the \"Rounded Rectangle\"\n shape option (its ShapeTypeMenu draws a bordered span, because the icon set\n has one rectangle glyph and it is already taken by \"Rectangle\"). */\nconst RoundedRectangleOutline = styled.span`\n display: block;\n width: 16px;\n height: 16px;\n box-sizing: border-box;\n border: 1px solid currentColor;\n border-radius: 4px;\n`;\n\nexport const SHAPE_TYPE_ICON: Record<ShapeType, ReactElement> = {\n rectangle: <RoundedRectangleIcon className=\"i16\" />,\n roundedRectangle: <RoundedRectangleOutline aria-hidden=\"true\" />,\n circle: <CircleIcon className=\"i16\" />,\n triangle: <TriangleIcon className=\"i16\" />,\n};\n\n/* The four shape types, in the order the shape-type menu lists them. */\nexport const SHAPE_TYPE_OPTIONS: { type: ShapeType; label: string }[] = [\n { type: \"rectangle\", label: \"Rectangle\" },\n { type: \"roundedRectangle\", label: \"Rounded Rectangle\" },\n { type: \"circle\", label: \"Circle\" },\n { type: \"triangle\", label: \"Triangle\" },\n];\n\n/* Stroke pattern options — now only the Inspector's Stroke group renders these\n (the shape floating toolbar no longer edits stroke). Mirrors the app's\n STROKE_PATTERN_OPTIONS dash enum: solid | dashed | dotted. */\nexport const BORDER_STYLE_OPTIONS: {\n value?: ShapeElementState[\"strokeDash\"];\n label: string;\n}[] = [\n { value: undefined, label: \"Solid\" },\n { value: \"5,5\", label: \"Dashed\" },\n { value: \"2,2\", label: \"Dotted\" },\n];\n\n/* ── Shared floating-toolbar controls ───────────────────────────────────────\n The floating toolbars were flattened this session to match the app: compact,\n collapsed controls (single-button dropdowns) with uniform 4px spacing and a\n single hairline separator only before Lock / Delete. These mirror the shared\n controls in the app's Inspector/Controls (ShapeTypeMenu, AlignmentMenu,\n ColorPicker compact, ToolbarActions). */\n\n/* ToolbarActions — the trailing block shared by EVERY floating toolbar:\n separator → Lock → Delete, in the standard control colour (not red). Mirrors\n app `toolbar/ToolbarActions.jsx`. */\nexport interface ToolbarActionsProps {\n locked: boolean;\n onToggleLock: () => void;\n onDelete: () => void;\n}\n\nexport const ToolbarActions = ({\n locked,\n onToggleLock,\n onDelete,\n}: ToolbarActionsProps): ReactElement => (\n <>\n <span className=\"divider\" />\n <Tooltip title={locked ? \"Unlock\" : \"Lock\"}>\n <StyledToolbarButton\n className={locked ? \"icon-only active\" : \"icon-only\"}\n aria-pressed={locked}\n onClick={onToggleLock}\n >\n <LockIcon className=\"i16\" />\n </StyledToolbarButton>\n </Tooltip>\n <Tooltip title=\"Delete\">\n <StyledToolbarButton className=\"icon-only\" onClick={onDelete}>\n <TrashIcon className=\"i16\" />\n </StyledToolbarButton>\n </Tooltip>\n </>\n);\n\n/* ShapeTypeMenu — collapsed shape-type picker: one icon button showing the\n current shape, opening a dropdown of the four types. Modeled on the app's\n ShapeTypeMenu (DS Menu + List). */\nexport interface ToolbarShapeTypeMenuProps {\n value: ShapeType;\n onChange: (type: ShapeType) => void;\n}\n\nexport const ShapeTypeMenu = ({\n value,\n onChange,\n}: ToolbarShapeTypeMenuProps): ReactElement => {\n const [open, setOpen] = useState(false);\n\n return (\n <Menu\n open={open}\n onOpen={() => setOpen(true)}\n onClose={() => setOpen(false)}\n position=\"bottom-start\"\n target={\n <IconButton\n type=\"button\"\n variant=\"option\"\n active={open}\n aria-label=\"Shape\"\n >\n {SHAPE_TYPE_ICON[value]}\n </IconButton>\n }\n >\n <List style={{ padding: \"8px 0\" }} tabIndex={-1}>\n {SHAPE_TYPE_OPTIONS.map((option) => (\n <ListItem\n key={option.type}\n aria-label={option.label}\n onClick={() => {\n onChange(option.type);\n setOpen(false);\n }}\n >\n {SHAPE_TYPE_ICON[option.type]}\n {option.label}\n </ListItem>\n ))}\n </List>\n </Menu>\n );\n};\n\n/* AlignmentMenu — collapsed alignment picker (single button + dropdown), the\n compact-toolbar counterpart to the Inspector's expanded four-button row.\n Mirrors the app's AlignmentMenu. */\nexport interface ToolbarAlignmentMenuProps {\n value: TextAlign;\n onChange: (align: TextAlign) => void;\n disabled?: boolean;\n}\n\nexport const AlignmentMenu = ({\n value,\n onChange,\n disabled,\n}: ToolbarAlignmentMenuProps): ReactElement => {\n const [open, setOpen] = useState(false);\n const selected =\n ALIGN_OPTIONS.find((option) => option.value === value) ?? ALIGN_OPTIONS[0];\n\n return (\n <Menu\n open={open}\n onOpen={() => setOpen(true)}\n onClose={() => setOpen(false)}\n position=\"bottom-start\"\n target={\n <IconButton\n type=\"button\"\n variant=\"option\"\n active={open}\n disabled={disabled}\n aria-label=\"Alignment\"\n >\n {selected.icon}\n </IconButton>\n }\n >\n <List style={{ padding: \"8px 0\" }} tabIndex={-1}>\n {ALIGN_OPTIONS.map((option) => (\n <ListItem\n key={option.value}\n aria-label={option.label}\n onClick={() => {\n onChange(option.value);\n setOpen(false);\n }}\n >\n {option.icon}\n {option.label}\n </ListItem>\n ))}\n </List>\n </Menu>\n );\n};\n\n/* The app's compact `ColorPicker`: a DS `Select` whose trigger is the swatch\n alone (a Dot, or the CircleSlash chip when transparent) and whose menu is the\n standard dot-and-name list — the same control the Inspector's colour field\n uses, minus the name on the trigger. `includeTransparent` adds \"Transparent\"\n first: shape fill opts in, sticky fill and text colour do not. */\nexport interface ToolbarColorSwatchProps {\n value: string;\n includeTransparent?: boolean;\n label: string;\n onChange: (color: string) => void;\n}\n\nconst TOOLBAR_TRANSPARENT_OPTION = {\n id: \"transparent\",\n name: \"Transparent\",\n color: \"transparent\",\n textColor: \"transparent\",\n};\n\nconst sameHex = (a: string, b: string): boolean =>\n a.toLowerCase() === b.toLowerCase();\n\nconst ColorDot = ({ color }: { color: string }): ReactElement =>\n sameHex(color, \"transparent\") ? (\n <CircleSlashIcon width={16} height={16} fill=\"currentColor\" />\n ) : (\n <Dot color={color} size={16} />\n );\n\nexport const ToolbarColorSwatch = ({\n value,\n includeTransparent,\n label,\n onChange,\n}: ToolbarColorSwatchProps): ReactElement => {\n const options = includeTransparent\n ? [TOOLBAR_TRANSPARENT_OPTION, ...COLOR_OPTIONS]\n : COLOR_OPTIONS;\n const selected =\n options.find((option) => sameHex(option.id, value))?.id ?? value;\n\n return (\n <Tooltip title={label}>\n <span className=\"tb-rel\">\n <Select\n type=\"single\"\n disableSearch\n forceCloseMenu\n keepSameOptionsOrder\n options={options}\n selected={selected}\n onChange={(next) =>\n onChange(String(Array.isArray(next) ? next[0] : next))\n }\n renderOption={(option) => (\n <span className=\"tb-color-option\">\n <ColorDot color={String(option.id)} />\n {option.name}\n </span>\n )}\n target={\n <SelectTrigger\n aria-label={label}\n style={{\n width: TOOLBAR_COLOR_TRIGGER_WIDTH,\n paddingLeft: 8,\n paddingRight: 8,\n }}\n >\n <span className=\"tb-color-value\">\n <ColorDot color={value} />\n </span>\n </SelectTrigger>\n }\n />\n </span>\n </Tooltip>\n );\n};\n\n/* The app's `ValuePicker` for the font size: a DS `Select` over the fixed size\n ladder, its trigger reading \"16 pt\". */\nexport interface ToolbarFontSizeSelectProps {\n value: number;\n onChange: (size: number) => void;\n}\n\nexport const ToolbarFontSizeSelect = ({\n value,\n onChange,\n}: ToolbarFontSizeSelectProps): ReactElement => (\n <Tooltip title=\"Font Size\">\n <span className=\"tb-rel\">\n <Select\n type=\"single\"\n disableSearch\n forceCloseMenu\n keepSameOptionsOrder\n options={FONT_SIZE_OPTIONS.map((size) => ({\n id: size,\n name: `${size} pt`,\n }))}\n selected={value}\n onChange={(next) =>\n onChange(Number(Array.isArray(next) ? next[0] : next))\n }\n target={\n <SelectTrigger\n aria-label=\"Font Size\"\n style={{ width: TOOLBAR_SELECT_WIDTH }}\n >\n {value} pt\n </SelectTrigger>\n }\n />\n </span>\n </Tooltip>\n);\n\n/* The text controls shared by the shape and sticky toolbars: font-size select,\n B / I / U / S, and the collapsed alignment menu. Same set the app's sticky\n and shape toolbars share (font-size picker, TextStyleButtons, AlignmentMenu).\n Kept generic so both element shapes can drive it. */\nexport interface ToolbarTextControlsProps {\n fontSize: number;\n styleFlags: {\n bold: boolean;\n italic: boolean;\n underline: boolean;\n strikethrough: boolean;\n };\n align: TextAlign;\n onFontSize: (size: number) => void;\n onToggleStyle: (key: TextStyleKey) => void;\n onAlign: (align: TextAlign) => void;\n}\n\nexport const ToolbarTextControls = ({\n fontSize,\n styleFlags,\n align,\n onFontSize,\n onToggleStyle,\n onAlign,\n}: ToolbarTextControlsProps): ReactElement => (\n <>\n <ToolbarFontSizeSelect value={fontSize} onChange={onFontSize} />\n {STYLE_OPTIONS.map((option) => (\n <Tooltip key={option.key} title={option.label}>\n <StyledToolbarButton\n className={styleFlags[option.key] ? \"icon-only active\" : \"icon-only\"}\n aria-label={option.label}\n aria-pressed={styleFlags[option.key]}\n onClick={() => onToggleStyle(option.key)}\n >\n {option.icon}\n </StyledToolbarButton>\n </Tooltip>\n ))}\n <AlignmentMenu value={align} onChange={onAlign} />\n </>\n);\n\nexport interface ShapeFormattingToolbarProps {\n element: ShapeElementState;\n onUpdate: (partial: Partial<ShapeElementState>) => void;\n onDelete: () => void;\n locked: boolean;\n onToggleLock: () => void;\n}\n\n/* ShapeFormattingToolbar — flat layout (was submenu-based): shape-type menu →\n fill colour → the same text controls as the sticky toolbar → Lock / Delete.\n Stroke is no longer edited here — it lives only in the Inspector's Stroke\n group now. Mirrors the app's ShapeFormattingToolbar. */\nexport const ShapeFormattingToolbar = ({\n element,\n onUpdate,\n onDelete,\n locked,\n onToggleLock,\n}: ShapeFormattingToolbarProps): ReactElement => (\n <StyledFormattingToolbar onClick={stopClick} onMouseDown={stopClick}>\n <ShapeTypeMenu\n value={element.type}\n onChange={(type) => onUpdate({ type })}\n />\n <ToolbarColorSwatch\n value={element.fill}\n includeTransparent\n label=\"Fill color\"\n onChange={(fill) => onUpdate({ fill })}\n />\n <ToolbarTextControls\n fontSize={element.fontSize}\n styleFlags={element}\n align={element.align ?? \"left\"}\n onFontSize={(fontSize) => onUpdate({ fontSize })}\n onToggleStyle={(key) => onUpdate({ [key]: !element[key] })}\n onAlign={(align) => onUpdate({ align })}\n />\n <ToolbarActions\n locked={locked}\n onToggleLock={onToggleLock}\n onDelete={onDelete}\n />\n </StyledFormattingToolbar>\n);\n\nexport interface StickyTextStyle {\n fontSize: number;\n bold: boolean;\n italic: boolean;\n strikethrough: boolean;\n underline: boolean;\n align: TextAlign;\n textColor: string;\n color: string;\n fillOpacity: number;\n}\n\nexport interface PostitFormattingToolbarProps {\n value: StickyTextStyle;\n onChange: (next: StickyTextStyle) => void;\n onDelete: () => void;\n locked: boolean;\n onToggleLock: () => void;\n}\n\n/* PostitFormattingToolbar — flat layout: note (fill) colour → the shared text\n controls (font-size, B/I/U/S, alignment menu) → Lock / Delete. The note's\n colour is its whole point, so its fill swatch does NOT offer Transparent.\n Mirrors the app's PostitFormattingToolbar. */\nexport const PostitFormattingToolbar = ({\n value,\n onChange,\n onDelete,\n locked,\n onToggleLock,\n}: PostitFormattingToolbarProps): ReactElement => (\n <StyledFormattingToolbar onClick={stopClick} onMouseDown={stopClick}>\n <ToolbarColorSwatch\n value={value.color}\n label=\"Note color\"\n onChange={(color) => onChange({ ...value, color })}\n />\n <ToolbarTextControls\n fontSize={value.fontSize}\n styleFlags={value}\n align={value.align}\n onFontSize={(fontSize) => onChange({ ...value, fontSize })}\n onToggleStyle={(key) => onChange({ ...value, [key]: !value[key] })}\n onAlign={(align) => onChange({ ...value, align })}\n />\n <ToolbarActions\n locked={locked}\n onToggleLock={onToggleLock}\n onDelete={onDelete}\n />\n </StyledFormattingToolbar>\n);\n\n/* shape body per current (editable) type */\nexport const renderShapeBody = (\n def: CanvasElementDef,\n state: ShapeElementState,\n /* Effective size — the Inspector can override the element's default width /\n height, so the triangle polygon is drawn from the live size, not the def. */\n width: number = def.width,\n height: number = def.height\n): ReactElement =>\n state.type === \"triangle\" ? (\n /* TriangleElement: SVG polygon, apex top-center */\n <svg\n width=\"100%\"\n height=\"100%\"\n style={{ display: \"block\", overflow: \"visible\" }}\n >\n <polygon\n points={`${width / 2},0 ${width},${height} 0,${height}`}\n fill={withOpacity(state.fill, state.fillOpacity)}\n stroke={withOpacity(state.stroke, state.strokeOpacity)}\n strokeWidth={state.strokeWidth}\n strokeDasharray={state.strokeDash}\n />\n </svg>\n ) : (\n <div\n className=\"shape-fill\"\n style={{\n backgroundColor: withOpacity(state.fill, state.fillOpacity),\n border: shapeBorder(state),\n borderRadius: state.type === \"circle\" ? \"50%\" : state.borderRadius,\n }}\n />\n );\n\nexport const ALIGN_OPTIONS: {\n value: TextAlign;\n label: string;\n icon: ReactElement;\n}[] = [\n { value: \"left\", label: \"Align Left\", icon: <TextAlignLeftIcon /> },\n { value: \"center\", label: \"Align Center\", icon: <TextAlignCenterIcon /> },\n { value: \"right\", label: \"Align Right\", icon: <TextAlignRightIcon /> },\n { value: \"justify\", label: \"Justify\", icon: <TextAlignJustifyIcon /> },\n];\n\nexport type TextStyleKey = \"bold\" | \"italic\" | \"underline\" | \"strikethrough\";\n\nexport const STYLE_OPTIONS: {\n key: TextStyleKey;\n label: string;\n icon: ReactElement;\n}[] = [\n { key: \"bold\", label: \"Bold\", icon: <TextStyleBoldIcon /> },\n { key: \"italic\", label: \"Italic\", icon: <TextStyleItalicIcon /> },\n { key: \"underline\", label: \"Underline\", icon: <TextStyleUnderlineIcon /> },\n {\n key: \"strikethrough\",\n label: \"Strikethrough\",\n icon: <TextStyleStrikeIcon />,\n },\n];\n"],"mappings":"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","ignoreList":[]}
@@ -1 +1 @@
1
- {"version":3,"file":"entityCardActions.d.ts","sourceRoot":"","sources":["../../../../src/presentation/whiteboard/entityCardActions.tsx"],"names":[],"mappings":"AAAA,OAAc,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAQ5C,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,WAAW,CAAC;AAMxD;;;;;;;;;;;;;;GAcG;AACH,MAAM,WAAW,sBAAsB;IACrC,SAAS,EAAE,MAAM,IAAI,CAAC;IACtB,MAAM,EAAE,OAAO,CAAC;IAChB,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,QAAQ,EAAE,MAAM,IAAI,CAAC;CACtB;AAED,eAAO,MAAM,iBAAiB,GAAI,gDAK/B,sBAAsB,KAAG,YAe3B,CAAC;AAEF;;;;;;;;;GASG;AACH,eAAO,MAAM,kBAAkB,GAC7B,QAAQ,YAAY,KACnB,IAAI,CAAC,sBAAsB,EAAE,MAAM,GAAG,SAAS,CAgBjD,CAAC"}
1
+ {"version":3,"file":"entityCardActions.d.ts","sourceRoot":"","sources":["../../../../src/presentation/whiteboard/entityCardActions.tsx"],"names":[],"mappings":"AAAA,OAAc,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAQ5C,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEjD,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,WAAW,CAAC;AAMxD;;;;;;;;;;;;;;GAcG;AACH,MAAM,WAAW,sBAAsB;IACrC,SAAS,EAAE,MAAM,IAAI,CAAC;IACtB,MAAM,EAAE,OAAO,CAAC;IAChB,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,QAAQ,EAAE,MAAM,IAAI,CAAC;CACtB;AAED,eAAO,MAAM,iBAAiB,GAAI,gDAK/B,sBAAsB,KAAG,YAgB3B,CAAC;AAEF;;;;;;;;;GASG;AACH,eAAO,MAAM,kBAAkB,GAC7B,QAAQ,YAAY,KACnB,IAAI,CAAC,sBAAsB,EAAE,MAAM,GAAG,SAAS,CAgBjD,CAAC"}
@@ -1,5 +1,6 @@
1
1
  import React from "react";
2
2
  import { StyledFormattingToolbar, StyledToolbarButton, ToolbarActions, stopClick } from "./elements";
3
+ import { InfoIcon } from "../../components/Icons";
3
4
 
4
5
  /* ------------------------------------------------------------------ */
5
6
  /* Selection menu for the person element */
@@ -33,7 +34,9 @@ export const PersonCardToolbar = _ref => {
33
34
  }, /*#__PURE__*/React.createElement(StyledToolbarButton, {
34
35
  type: "button",
35
36
  onClick: onDetails
36
- }, "Details"), /*#__PURE__*/React.createElement(ToolbarActions, {
37
+ }, /*#__PURE__*/React.createElement(InfoIcon, {
38
+ className: "i16"
39
+ }), "Details"), /*#__PURE__*/React.createElement(ToolbarActions, {
37
40
  locked: locked,
38
41
  onToggleLock: onToggleLock,
39
42
  onDelete: onDelete
@@ -1 +1 @@
1
- {"version":3,"file":"entityCardActions.js","names":["React","StyledFormattingToolbar","StyledToolbarButton","ToolbarActions","stopClick","PersonCardToolbar","_ref","onDetails","locked","onToggleLock","onDelete","createElement","onMouseDown","onClick","type","personDetailsProps","person","firstName","name","split","toLowerCase","replace","avatar","color","initials","hoursLabel","email","extraContactsCount","joinedDate","onSendMessage","undefined","onSeeFullProfile"],"sources":["../../../../src/presentation/whiteboard/entityCardActions.tsx"],"sourcesContent":["import React, { ReactElement } from \"react\";\n\nimport {\n StyledFormattingToolbar,\n StyledToolbarButton,\n ToolbarActions,\n stopClick,\n} from \"./elements\";\nimport { PickerPerson } from \"./projectElements\";\nimport type { UserDetailsDialogProps } from \"../shared\";\n\n/* ------------------------------------------------------------------ */\n/* Selection menu for the person element */\n/* ------------------------------------------------------------------ */\n\n/**\n * The selection toolbar for a PERSON element.\n *\n * A person is not a page you visit and not a link you copy — it is an avatar\n * chip — so its bar drops both of the entity card's leading actions and offers\n * exactly one: Details, which opens the user details dialog. The trailing\n * `ToolbarActions` block (separator → Lock → Delete) is the same one every other\n * element on this board carries, so the bar reads as: Details | (sep) Lock |\n * Delete.\n *\n * Which STATES get a toolbar is the caller's business (the canvas layer already\n * knows every element's status): only a resolved, non-limited person does. A\n * limited person must not offer a single one of these, and a placeholder or a\n * resolving skeleton has no person to act on yet.\n */\nexport interface PersonCardToolbarProps {\n onDetails: () => void;\n locked: boolean;\n onToggleLock: () => void;\n onDelete: () => void;\n}\n\nexport const PersonCardToolbar = ({\n onDetails,\n locked,\n onToggleLock,\n onDelete,\n}: PersonCardToolbarProps): ReactElement => (\n <StyledFormattingToolbar\n data-testid=\"wb-person-toolbar\"\n onMouseDown={stopClick}\n onClick={stopClick}\n >\n <StyledToolbarButton type=\"button\" onClick={onDetails}>\n Details\n </StyledToolbarButton>\n <ToolbarActions\n locked={locked}\n onToggleLock={onToggleLock}\n onDelete={onDelete}\n />\n </StyledFormattingToolbar>\n);\n\n/**\n * The person data the whiteboard feeds the reusable `UserDetailsDialog` when a\n * person's Details button is clicked.\n *\n * The board only knows a person's name / initials / avatar colour, so the rest\n * of the dialog's fields are representative sample data (a working-hours pill, a\n * derived email with one extra contact, and a joined date) — the dialog itself\n * takes everything as props and hardcodes none of it. `open` and `onClose` are\n * supplied by the caller that renders the dialog.\n */\nexport const personDetailsProps = (\n person: PickerPerson\n): Omit<UserDetailsDialogProps, \"open\" | \"onClose\"> => {\n const firstName = person.name\n .split(\" \")[0]\n .toLowerCase()\n .replace(/[^a-z]/g, \"\");\n\n return {\n avatar: { color: person.color, initials: person.initials },\n name: person.name,\n hoursLabel: \"40 h/w\",\n email: `${firstName || person.initials.toLowerCase()}@activecollab.com`,\n extraContactsCount: 1,\n joinedDate: \"Joined: Feb 7. 2009\",\n onSendMessage: () => undefined,\n onSeeFullProfile: () => undefined,\n };\n};\n"],"mappings":"AAAA,OAAOA,KAAK,MAAwB,OAAO;AAE3C,SACEC,uBAAuB,EACvBC,mBAAmB,EACnBC,cAAc,EACdC,SAAS,QACJ,YAAY;;AAInB;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAQA,OAAO,MAAMC,iBAAiB,GAAGC,IAAA;EAAA,IAC/BC,SAAS,GAAAD,IAAA,CAATC,SAAS;IACTC,MAAM,GAAAF,IAAA,CAANE,MAAM;IACNC,YAAY,GAAAH,IAAA,CAAZG,YAAY;IACZC,QAAQ,GAAAJ,IAAA,CAARI,QAAQ;EAAA,oBAERV,KAAA,CAAAW,aAAA,CAACV,uBAAuB;IACtB,eAAY,mBAAmB;IAC/BW,WAAW,EAAER,SAAU;IACvBS,OAAO,EAAET;EAAU,gBAEnBJ,KAAA,CAAAW,aAAA,CAACT,mBAAmB;IAACY,IAAI,EAAC,QAAQ;IAACD,OAAO,EAAEN;EAAU,GAAC,SAElC,CAAC,eACtBP,KAAA,CAAAW,aAAA,CAACR,cAAc;IACbK,MAAM,EAAEA,MAAO;IACfC,YAAY,EAAEA,YAAa;IAC3BC,QAAQ,EAAEA;EAAS,CACpB,CACsB,CAAC;AAAA,CAC3B;;AAED;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,MAAMK,kBAAkB,GAC7BC,MAAoB,IACiC;EACrD,MAAMC,SAAS,GAAGD,MAAM,CAACE,IAAI,CAC1BC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CACbC,WAAW,CAAC,CAAC,CACbC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC;EAEzB,OAAO;IACLC,MAAM,EAAE;MAAEC,KAAK,EAAEP,MAAM,CAACO,KAAK;MAAEC,QAAQ,EAAER,MAAM,CAACQ;IAAS,CAAC;IAC1DN,IAAI,EAAEF,MAAM,CAACE,IAAI;IACjBO,UAAU,EAAE,QAAQ;IACpBC,KAAK,GAAKT,SAAS,IAAID,MAAM,CAACQ,QAAQ,CAACJ,WAAW,CAAC,CAAC,uBAAmB;IACvEO,kBAAkB,EAAE,CAAC;IACrBC,UAAU,EAAE,qBAAqB;IACjCC,aAAa,EAAEA,CAAA,KAAMC,SAAS;IAC9BC,gBAAgB,EAAEA,CAAA,KAAMD;EAC1B,CAAC;AACH,CAAC","ignoreList":[]}
1
+ {"version":3,"file":"entityCardActions.js","names":["React","StyledFormattingToolbar","StyledToolbarButton","ToolbarActions","stopClick","InfoIcon","PersonCardToolbar","_ref","onDetails","locked","onToggleLock","onDelete","createElement","onMouseDown","onClick","type","className","personDetailsProps","person","firstName","name","split","toLowerCase","replace","avatar","color","initials","hoursLabel","email","extraContactsCount","joinedDate","onSendMessage","undefined","onSeeFullProfile"],"sources":["../../../../src/presentation/whiteboard/entityCardActions.tsx"],"sourcesContent":["import React, { ReactElement } from \"react\";\n\nimport {\n StyledFormattingToolbar,\n StyledToolbarButton,\n ToolbarActions,\n stopClick,\n} from \"./elements\";\nimport { PickerPerson } from \"./projectElements\";\nimport { InfoIcon } from \"../../components/Icons\";\nimport type { UserDetailsDialogProps } from \"../shared\";\n\n/* ------------------------------------------------------------------ */\n/* Selection menu for the person element */\n/* ------------------------------------------------------------------ */\n\n/**\n * The selection toolbar for a PERSON element.\n *\n * A person is not a page you visit and not a link you copy — it is an avatar\n * chip — so its bar drops both of the entity card's leading actions and offers\n * exactly one: Details, which opens the user details dialog. The trailing\n * `ToolbarActions` block (separator → Lock → Delete) is the same one every other\n * element on this board carries, so the bar reads as: Details | (sep) Lock |\n * Delete.\n *\n * Which STATES get a toolbar is the caller's business (the canvas layer already\n * knows every element's status): only a resolved, non-limited person does. A\n * limited person must not offer a single one of these, and a placeholder or a\n * resolving skeleton has no person to act on yet.\n */\nexport interface PersonCardToolbarProps {\n onDetails: () => void;\n locked: boolean;\n onToggleLock: () => void;\n onDelete: () => void;\n}\n\nexport const PersonCardToolbar = ({\n onDetails,\n locked,\n onToggleLock,\n onDelete,\n}: PersonCardToolbarProps): ReactElement => (\n <StyledFormattingToolbar\n data-testid=\"wb-person-toolbar\"\n onMouseDown={stopClick}\n onClick={stopClick}\n >\n <StyledToolbarButton type=\"button\" onClick={onDetails}>\n <InfoIcon className=\"i16\" />\n Details\n </StyledToolbarButton>\n <ToolbarActions\n locked={locked}\n onToggleLock={onToggleLock}\n onDelete={onDelete}\n />\n </StyledFormattingToolbar>\n);\n\n/**\n * The person data the whiteboard feeds the reusable `UserDetailsDialog` when a\n * person's Details button is clicked.\n *\n * The board only knows a person's name / initials / avatar colour, so the rest\n * of the dialog's fields are representative sample data (a working-hours pill, a\n * derived email with one extra contact, and a joined date) — the dialog itself\n * takes everything as props and hardcodes none of it. `open` and `onClose` are\n * supplied by the caller that renders the dialog.\n */\nexport const personDetailsProps = (\n person: PickerPerson\n): Omit<UserDetailsDialogProps, \"open\" | \"onClose\"> => {\n const firstName = person.name\n .split(\" \")[0]\n .toLowerCase()\n .replace(/[^a-z]/g, \"\");\n\n return {\n avatar: { color: person.color, initials: person.initials },\n name: person.name,\n hoursLabel: \"40 h/w\",\n email: `${firstName || person.initials.toLowerCase()}@activecollab.com`,\n extraContactsCount: 1,\n joinedDate: \"Joined: Feb 7. 2009\",\n onSendMessage: () => undefined,\n onSeeFullProfile: () => undefined,\n };\n};\n"],"mappings":"AAAA,OAAOA,KAAK,MAAwB,OAAO;AAE3C,SACEC,uBAAuB,EACvBC,mBAAmB,EACnBC,cAAc,EACdC,SAAS,QACJ,YAAY;AAEnB,SAASC,QAAQ,QAAQ,wBAAwB;;AAGjD;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAQA,OAAO,MAAMC,iBAAiB,GAAGC,IAAA;EAAA,IAC/BC,SAAS,GAAAD,IAAA,CAATC,SAAS;IACTC,MAAM,GAAAF,IAAA,CAANE,MAAM;IACNC,YAAY,GAAAH,IAAA,CAAZG,YAAY;IACZC,QAAQ,GAAAJ,IAAA,CAARI,QAAQ;EAAA,oBAERX,KAAA,CAAAY,aAAA,CAACX,uBAAuB;IACtB,eAAY,mBAAmB;IAC/BY,WAAW,EAAET,SAAU;IACvBU,OAAO,EAAEV;EAAU,gBAEnBJ,KAAA,CAAAY,aAAA,CAACV,mBAAmB;IAACa,IAAI,EAAC,QAAQ;IAACD,OAAO,EAAEN;EAAU,gBACpDR,KAAA,CAAAY,aAAA,CAACP,QAAQ;IAACW,SAAS,EAAC;EAAK,CAAE,CAAC,WAET,CAAC,eACtBhB,KAAA,CAAAY,aAAA,CAACT,cAAc;IACbM,MAAM,EAAEA,MAAO;IACfC,YAAY,EAAEA,YAAa;IAC3BC,QAAQ,EAAEA;EAAS,CACpB,CACsB,CAAC;AAAA,CAC3B;;AAED;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,MAAMM,kBAAkB,GAC7BC,MAAoB,IACiC;EACrD,MAAMC,SAAS,GAAGD,MAAM,CAACE,IAAI,CAC1BC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CACbC,WAAW,CAAC,CAAC,CACbC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC;EAEzB,OAAO;IACLC,MAAM,EAAE;MAAEC,KAAK,EAAEP,MAAM,CAACO,KAAK;MAAEC,QAAQ,EAAER,MAAM,CAACQ;IAAS,CAAC;IAC1DN,IAAI,EAAEF,MAAM,CAACE,IAAI;IACjBO,UAAU,EAAE,QAAQ;IACpBC,KAAK,GAAKT,SAAS,IAAID,MAAM,CAACQ,QAAQ,CAACJ,WAAW,CAAC,CAAC,uBAAmB;IACvEO,kBAAkB,EAAE,CAAC;IACrBC,UAAU,EAAE,qBAAqB;IACjCC,aAAa,EAAEA,CAAA,KAAMC,SAAS;IAC9BC,gBAAgB,EAAEA,CAAA,KAAMD;EAC1B,CAAC;AACH,CAAC","ignoreList":[]}
@@ -2,7 +2,7 @@ import _extends from "@babel/runtime/helpers/esm/extends";
2
2
  import React, { useCallback, useEffect, useRef, useState } from "react";
3
3
  import styled from "styled-components";
4
4
  import { StyledFormattingToolbar, StyledToolbarButton, stopClick } from "./elements";
5
- import { ArrowRefreshIcon, AttachmentIcon, CancelCrossIcon, DownloadIcon, TrashIcon, UploadIcon } from "../../components/Icons";
5
+ import { ArrowRefreshIcon, AttachmentIcon, CloseIcon, DownloadIcon, TrashIcon, UploadIcon } from "../../components/Icons";
6
6
  import { SpinnerLoader } from "../../components/Loaders";
7
7
  import { ProgressRing } from "../../components/ProgressRing";
8
8
  import { StackedCard, StackedCardCover, StackedCardRow } from "../../components/StackedCard";
@@ -241,7 +241,7 @@ export const FileFormattingToolbar = _ref2 => {
241
241
  }), "Upload") : null, status === "uploading" || status === "preparing" ? /*#__PURE__*/React.createElement(StyledToolbarButton, {
242
242
  type: "button",
243
243
  onClick: onCancel
244
- }, /*#__PURE__*/React.createElement(CancelCrossIcon, {
244
+ }, /*#__PURE__*/React.createElement(CloseIcon, {
245
245
  className: "i16"
246
246
  }), "Cancel") : null, status === "error" ? /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(StyledToolbarButton, {
247
247
  type: "button",
@@ -251,7 +251,7 @@ export const FileFormattingToolbar = _ref2 => {
251
251
  }), "Retry"), /*#__PURE__*/React.createElement(StyledToolbarButton, {
252
252
  type: "button",
253
253
  onClick: onCancel
254
- }, /*#__PURE__*/React.createElement(CancelCrossIcon, {
254
+ }, /*#__PURE__*/React.createElement(CloseIcon, {
255
255
  className: "i16"
256
256
  }), "Cancel")) : null, status === "ready" ? /*#__PURE__*/React.createElement(StyledToolbarButton, {
257
257
  type: "button"
@@ -1 +1 @@
1
- {"version":3,"file":"fileElement.js","names":["React","useCallback","useEffect","useRef","useState","styled","StyledFormattingToolbar","StyledToolbarButton","stopClick","ArrowRefreshIcon","AttachmentIcon","CancelCrossIcon","DownloadIcon","TrashIcon","UploadIcon","SpinnerLoader","ProgressRing","StackedCard","StackedCardCover","StackedCardRow","Tooltip","Body2","Caption1","Caption2","COVER_RATIO_IMAGE","Placeholder","FILE_DEFAULT_WIDTH","MAX_UPLOAD_BYTES","UPLOAD_TICK_MS","UPLOAD_STEP","PREPARING_MS","FILE_SIZE_UNITS","formatFileSize","value","_ref","unit","bytes","inUnit","toFixed","Math","trunc","describeFile","file","dot","name","lastIndexOf","hasExtension","base","slice","extension","size","mimeType","type","thumbnailUrl","startsWith","URL","createObjectURL","revokeThumbnail","revokeObjectURL","binaryFrom","data","files","length","item","Array","from","_data$items","items","kind","picked","getAsFile","useMockUpload","_useState","status","setStatus","_useState2","progress","setProgress","timers","ticker","progressRef","clearAll","current","forEach","clearTimeout","clearInterval","retry","push","setTimeout","setInterval","min","StyledFileCard","withConfig","displayName","componentId","StyledUploadCover","div","StyledFileFallback","StyledFileName","StyledDropOverlay","StyledHiddenFileInput","input","StyledPlaceholderBox","FilePlaceholder","props","createElement","_extends","icon","label","dashed","FileFormattingToolbar","_ref2","onPick","onCancel","onRetry","onDelete","onMouseDown","onClick","className","Fragment","title","FileUploadCard","_ref3","element","selected","resize","upload","ready","resizable","resizeAxis","resizeLabel","aspectRatio","renderFileThumbnail","radius","stroke","weight","color","style","cursor","role","src","alt","toUpperCase","FileElement","_ref4","autoOpen","onPickFile","inputRef","_useState3","dropping","setDropping","openPicker","_inputRef$current","click","handleInputChange","event","_event$target$files","target","handleDrop","preventDefault","stopPropagation","dropped","dataTransfer","ref","onChange","bleed","onDragEnter","onDragOver","onDragLeave","currentTarget","contains","relatedTarget","onDrop"],"sources":["../../../../src/presentation/whiteboard/fileElement.tsx"],"sourcesContent":["import React, {\n ReactElement,\n useCallback,\n useEffect,\n useRef,\n useState,\n} from \"react\";\n\nimport styled from \"styled-components\";\n\nimport {\n StyledFormattingToolbar,\n StyledToolbarButton,\n stopClick,\n} from \"./elements\";\nimport { CardResizeHandlers } from \"./linkElement\";\nimport {\n ArrowRefreshIcon,\n AttachmentIcon,\n CancelCrossIcon,\n DownloadIcon,\n TrashIcon,\n UploadIcon,\n} from \"../../components/Icons\";\nimport { SpinnerLoader } from \"../../components/Loaders\";\nimport { ProgressRing } from \"../../components/ProgressRing\";\nimport {\n StackedCard,\n StackedCardCover,\n StackedCardRow,\n} from \"../../components/StackedCard\";\nimport { Tooltip } from \"../../components/Tooltip\";\nimport { Body2, Caption1, Caption2 } from \"../../components/Typography\";\nimport { COVER_RATIO_IMAGE, Placeholder } from \"../stackedCard/content\";\n\n/* ------------------------------------------------------------------ */\n/* File element — the upload lifecycle + the file card */\n/* ------------------------------------------------------------------ */\n\n/**\n * The file card is the second element built on `StackedCard`, and it mirrors the\n * card in a project's Files tab (`Folders/GridView/Items/File.js`): a thumbnail\n * over a strip with the name, then size · date.\n *\n * Its lifecycle is the app's real upload lifecycle, which is two phases and not\n * one — the distinction the ring alone doesn't tell you:\n *\n * uploading XHR progress 0–100. `ProgressRing radius={22} stroke={4}` with\n * the percentage, exactly as `Items/FileUpload.js` does it.\n * preparing bytes are in, the server is generating the thumbnail. Progress\n * is no longer knowable, so the ring gives way to the\n * indeterminate `SpinnerLoader` at the same size — again as the\n * real card does at `progress === 100`.\n * ready the thumbnail exists; the card renders it.\n * error the upload failed: retry, same as the app's `ArrowRefreshIcon`.\n *\n * Both phases reserve the same box as the finished cover, so a card never\n * reflows as it climbs — the discipline the unfurl ladder established.\n */\n\n/* The Files-tab card is a fixed 208×208. On a canvas the width is the host's,\n so 208 is only the default a click-placed card takes. */\nexport const FILE_DEFAULT_WIDTH = 208;\n\n/* Big enough to be worth refusing, so the error state is reachable: the server\n enforces the real limits (and answers StorageOverusedError when full). */\nexport const MAX_UPLOAD_BYTES = 25 * 1024 * 1024;\n\nexport const UPLOAD_TICK_MS = 110;\nexport const UPLOAD_STEP = 9;\n/* How long the server spends making a thumbnail once the bytes have landed. */\nexport const PREPARING_MS = 1100;\n\n/** What the mock keeps about a picked file. */\nexport interface PickedFile {\n /** Name without the extension — truncates on its own. */\n base: string;\n /** Extension without the dot; never truncated, as in the real card. */\n extension: string;\n size: number;\n mimeType: string;\n /** An object URL, so an image really renders. Null for everything else. */\n thumbnailUrl: string | null;\n}\n\n/** A file element on the board. Position lives in the shared positions map. */\nexport interface FileElementDef {\n id: string;\n width: number;\n /** null while the card is an empty placeholder waiting for a file. */\n file: PickedFile | null;\n}\n\n/* Angie.functions.format_file_size — two decimals, no space, lower-case k.\n \"1.20MB\", not \"1.2 MB\". Reproduced exactly so the mock reads like the app. */\nexport const FILE_SIZE_UNITS: [string, number][] = [\n [\"TB\", 1099511627776],\n [\"GB\", 1073741824],\n [\"MB\", 1048576],\n [\"kB\", 1024],\n];\n\nexport const formatFileSize = (value: number): string => {\n for (const [unit, bytes] of FILE_SIZE_UNITS) {\n const inUnit = value / bytes;\n if (inUnit > 0.9) {\n return `${inUnit.toFixed(2)}${unit}`;\n }\n }\n\n return `${Math.trunc(value)}B`;\n};\n\nexport const describeFile = (file: File): PickedFile => {\n const dot = file.name.lastIndexOf(\".\");\n const hasExtension = dot > 0;\n\n return {\n base: hasExtension ? file.name.slice(0, dot) : file.name,\n extension: hasExtension ? file.name.slice(dot + 1) : \"\",\n size: file.size,\n mimeType: file.type,\n // Images get a real thumbnail; the server would generate one for every type,\n // but the mock can only show what the browser can already decode.\n thumbnailUrl: file.type.startsWith(\"image/\")\n ? URL.createObjectURL(file)\n : null,\n };\n};\n\n/* Object URLs are a manual allocation — release one whenever the file it stands\n for stops being on the board. */\nexport const revokeThumbnail = (file: PickedFile | null): void => {\n if (file?.thumbnailUrl) {\n URL.revokeObjectURL(file.thumbnailUrl);\n }\n};\n\n/** The first actual file on a clipboard or a drop, or null if there is none. */\nexport const binaryFrom = (data: DataTransfer | null): File | null => {\n if (!data) {\n return null;\n }\n\n if (data.files && data.files.length > 0) {\n return data.files[0];\n }\n\n // A screenshot paste arrives as an item, not in `files`.\n for (const item of Array.from(data.items ?? [])) {\n if (item.kind === \"file\") {\n const picked = item.getAsFile();\n if (picked) {\n return picked;\n }\n }\n }\n\n return null;\n};\n\nexport type UploadStatus = \"uploading\" | \"preparing\" | \"ready\" | \"error\";\n\nexport interface UploadController {\n status: UploadStatus;\n /** 0–100, as the app's XHR reports it. Only meaningful while uploading. */\n progress: number;\n retry: () => void;\n}\n\n/**\n * Drives one file through the upload lifecycle. Stands in for\n * `useFileHandler` + the XHR in `utils/upload.jsx`: ticks progress to 100,\n * hands over to the thumbnail phase, then resolves.\n */\nexport const useMockUpload = (file: PickedFile | null): UploadController => {\n const [status, setStatus] = useState<UploadStatus>(\"uploading\");\n const [progress, setProgress] = useState(0);\n\n const timers = useRef<ReturnType<typeof setTimeout>[]>([]);\n const ticker = useRef<ReturnType<typeof setInterval> | null>(null);\n const progressRef = useRef(0);\n\n const clearAll = useCallback(() => {\n timers.current.forEach(clearTimeout);\n timers.current = [];\n if (ticker.current) {\n clearInterval(ticker.current);\n ticker.current = null;\n }\n }, []);\n\n const retry = useCallback(() => {\n clearAll();\n progressRef.current = 0;\n setProgress(0);\n setStatus(\"uploading\");\n\n if (!file) {\n return;\n }\n\n if (file.size > MAX_UPLOAD_BYTES) {\n timers.current.push(setTimeout(() => setStatus(\"error\"), 700));\n\n return;\n }\n\n ticker.current = setInterval(() => {\n progressRef.current = Math.min(100, progressRef.current + UPLOAD_STEP);\n setProgress(progressRef.current);\n\n if (progressRef.current >= 100) {\n clearAll();\n // The bytes are up; the thumbnail is the server's job now.\n setStatus(\"preparing\");\n timers.current.push(setTimeout(() => setStatus(\"ready\"), PREPARING_MS));\n }\n }, UPLOAD_TICK_MS);\n }, [clearAll, file]);\n\n useEffect(() => {\n retry();\n\n return clearAll;\n }, [retry, clearAll]);\n\n return { status, progress, retry };\n};\n\n/* The card fills the box the board drew; height stays auto. */\nexport const StyledFileCard = styled(StackedCard)`\n && {\n width: 100%;\n }\n\n user-select: none;\n`;\n\n/* The cover while uploading or preparing — the ring/spinner centred in the box\n the finished thumbnail will occupy, so resolving never reflows the card. */\nexport const StyledUploadCover = styled.div`\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 10px;\n width: 100%;\n height: 100%;\n background-color: var(--color-theme-200);\n`;\n\n/* No thumbnail (the browser can't decode a .zip): the clip plus the extension.\n The real card has NO type-icon fallback — it renders a bare <img> and trusts\n the server — so this is net-new and worth a decision. */\nexport const StyledFileFallback = styled.div`\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 8px;\n width: 100%;\n height: 100%;\n background-color: var(--color-theme-200);\n color: var(--color-theme-600);\n\n > svg {\n width: 36px;\n height: 36px;\n fill: var(--color-theme-500);\n }\n`;\n\n/* Name row: the base name truncates, the extension never does — the same split\n the real card makes with removeExtensionFromFileName. */\nexport const StyledFileName = styled.div`\n display: flex;\n align-items: baseline;\n min-width: 0;\n width: 100%;\n\n .file-base {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n .file-ext {\n flex-shrink: 0;\n }\n`;\n\n/* The drop overlay, from directive.ang_drop_files.less: a near-opaque cover\n with a 2px dashed primary border and \"Drop here\". The app sets 24px type for\n a full-page target; on a card it reads at Body2. */\nexport const StyledDropOverlay = styled.div`\n position: absolute;\n inset: 0;\n z-index: 3;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 8px;\n box-sizing: border-box;\n background-color: var(--page-paper-main);\n\n .drop-box {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 100%;\n height: 100%;\n box-sizing: border-box;\n border: 2px dashed var(--color-primary);\n border-radius: 6px;\n }\n`;\n\nexport const StyledHiddenFileInput = styled.input`\n display: none;\n`;\n\n/* The placeholder reserves the same box the finished cover will occupy — the\n cover's ratio, not a pixel height — so attaching a file does not resize the\n card under the pointer. Placeholder's own fixed height is overridden here;\n the descendant selector outranks its class. */\nexport const StyledPlaceholderBox = styled.div`\n width: 100%;\n aspect-ratio: ${COVER_RATIO_IMAGE};\n\n > button {\n height: 100%;\n }\n`;\n\n/* The interactive empty state, in the shared placeholder frame the other card\n types use. Doubles as the drop target, like its copy promises. */\nexport const FilePlaceholder = (\n props: React.ButtonHTMLAttributes<HTMLButtonElement>\n): ReactElement => (\n <StyledPlaceholderBox>\n {/* Fills the card, so it has to be draggable as well as clickable. */}\n <Placeholder\n icon={<AttachmentIcon />}\n label=\"Drop a file or click to upload\"\n dashed\n data-drag-through=\"\"\n {...props}\n />\n </StyledPlaceholderBox>\n);\n\nexport interface FileToolbarProps {\n status: UploadStatus | \"placeholder\";\n /* Each phase only supplies the actions its own buttons need. */\n onPick?: () => void;\n onCancel?: () => void;\n onRetry?: () => void;\n onDelete: () => void;\n}\n\n/* The file element's floating toolbar. The leading action is whatever the\n current phase makes meaningful; Move to Trash is always available. */\nexport const FileFormattingToolbar = ({\n status,\n onPick,\n onCancel,\n onRetry,\n onDelete,\n}: FileToolbarProps): ReactElement => (\n <StyledFormattingToolbar onMouseDown={stopClick} onClick={stopClick}>\n {status === \"placeholder\" ? (\n <StyledToolbarButton type=\"button\" onClick={onPick}>\n <UploadIcon className=\"i16\" />\n Upload\n </StyledToolbarButton>\n ) : null}\n {status === \"uploading\" || status === \"preparing\" ? (\n <StyledToolbarButton type=\"button\" onClick={onCancel}>\n <CancelCrossIcon className=\"i16\" />\n Cancel\n </StyledToolbarButton>\n ) : null}\n {status === \"error\" ? (\n <>\n <StyledToolbarButton type=\"button\" onClick={onRetry}>\n <ArrowRefreshIcon className=\"i16\" />\n Retry\n </StyledToolbarButton>\n {/* A failed upload needs a way back to the placeholder too — otherwise\n a file that can never succeed leaves trashing the card as the only\n exit. */}\n <StyledToolbarButton type=\"button\" onClick={onCancel}>\n <CancelCrossIcon className=\"i16\" />\n Cancel\n </StyledToolbarButton>\n </>\n ) : null}\n {/* Inert, like the board's other export-shaped actions — there is no real\n stored file behind a mock. */}\n {status === \"ready\" ? (\n <StyledToolbarButton type=\"button\">\n <DownloadIcon className=\"i16\" />\n Download\n </StyledToolbarButton>\n ) : null}\n <span className=\"divider\" />\n <Tooltip title=\"Move to Trash\">\n <StyledToolbarButton\n type=\"button\"\n className=\"icon-only\"\n onClick={onDelete}\n >\n <TrashIcon className=\"i16\" />\n </StyledToolbarButton>\n </Tooltip>\n </StyledFormattingToolbar>\n);\n\nexport interface FileUploadCardProps {\n element: FileElementDef;\n selected: boolean;\n resize: CardResizeHandlers;\n onCancel: () => void;\n onDelete: () => void;\n}\n\n/**\n * A file element with a file attached: the card runs the upload lifecycle and\n * then renders the finished preview.\n */\nexport const FileUploadCard = ({\n element,\n selected,\n resize,\n onCancel,\n onDelete,\n}: FileUploadCardProps): ReactElement => {\n const file = element.file;\n const upload = useMockUpload(file);\n const ready = upload.status === \"ready\";\n\n return (\n <>\n <StyledFileCard\n selected={selected}\n resizable={selected}\n resizeAxis=\"width\"\n resizeLabel=\"Resize file card\"\n {...resize}\n >\n <StackedCardCover aspectRatio={COVER_RATIO_IMAGE}>\n {ready ? (\n renderFileThumbnail(file)\n ) : (\n <StyledUploadCover>\n {/* Determinate while the bytes move, indeterminate once they have\n landed — the app's own switch at progress === 100. */}\n {upload.status === \"uploading\" ? (\n <ProgressRing progress={upload.progress} radius={22} stroke={4}>\n <Caption2 weight=\"bold\" color=\"secondary\">\n {upload.progress}%\n </Caption2>\n </ProgressRing>\n ) : null}\n {upload.status === \"preparing\" ? (\n <SpinnerLoader radius={22} stroke={4} />\n ) : null}\n {upload.status === \"error\" ? (\n <ArrowRefreshIcon\n style={{ cursor: \"pointer\" }}\n onClick={upload.retry}\n />\n ) : null}\n <Caption2 color=\"tertiary\">\n {upload.status === \"uploading\" ? \"Uploading…\" : null}\n {upload.status === \"preparing\" ? \"Preparing preview…\" : null}\n {upload.status === \"error\" ? \"Upload failed\" : null}\n </Caption2>\n </StyledUploadCover>\n )}\n </StackedCardCover>\n\n <StackedCardRow role=\"title\">\n <StyledFileName>\n <Caption1 weight=\"bold\" className=\"file-base\">\n {file?.base}\n </Caption1>\n {file?.extension ? (\n <Caption1 weight=\"bold\" className=\"file-ext\">\n .{file.extension}\n </Caption1>\n ) : null}\n </StyledFileName>\n </StackedCardRow>\n\n {/* The real card hides its metadata until hover (max-height 0 → 55px).\n On a canvas the card is the object, not a row in a dense grid, so the\n line stays up — but it only says anything once the file exists. */}\n <StackedCardRow role=\"meta\">\n <Caption2 color=\"tertiary\">\n {ready && file ? `${formatFileSize(file.size)} · Just now` : \" \"}\n </Caption2>\n </StackedCardRow>\n </StyledFileCard>\n {selected ? (\n <FileFormattingToolbar\n status={upload.status}\n onCancel={onCancel}\n onRetry={upload.retry}\n onDelete={onDelete}\n />\n ) : null}\n </>\n );\n};\n\n/* An image renders for real; anything else falls back to the clip + extension. */\nexport const renderFileThumbnail = (file: PickedFile | null): ReactElement =>\n file?.thumbnailUrl ? (\n <img src={file.thumbnailUrl} alt=\"\" />\n ) : (\n <StyledFileFallback>\n <AttachmentIcon />\n <Caption2 color=\"tertiary\">\n {file?.extension ? file.extension.toUpperCase() : \"FILE\"}\n </Caption2>\n </StyledFileFallback>\n );\n\nexport interface FileElementProps {\n element: FileElementDef;\n selected: boolean;\n /** Open the file picker as soon as a freshly drawn placeholder lands. */\n autoOpen: boolean;\n onPickFile: (file: File) => void;\n resize: CardResizeHandlers;\n onCancel: () => void;\n onDelete: () => void;\n}\n\n/**\n * The two shapes of a file element: an empty placeholder that can be clicked or\n * dropped onto, and the uploading/ready card.\n *\n * A box drawn with the File tool opens the picker immediately. Dismissing the\n * picker fires no change, so the card simply stays a placeholder — which is what\n * makes Esc a no-op by construction rather than by handling.\n */\nexport const FileElement = ({\n element,\n selected,\n autoOpen,\n onPickFile,\n resize,\n onCancel,\n onDelete,\n}: FileElementProps): ReactElement => {\n const inputRef = useRef<HTMLInputElement | null>(null);\n const [dropping, setDropping] = useState(false);\n\n const openPicker = useCallback(() => {\n inputRef.current?.click();\n }, []);\n\n useEffect(() => {\n if (autoOpen) {\n openPicker();\n }\n }, [autoOpen, openPicker]);\n\n const handleInputChange = useCallback(\n (event: React.ChangeEvent<HTMLInputElement>): void => {\n const picked = event.target.files?.[0];\n if (picked) {\n onPickFile(picked);\n }\n // Let the same file be chosen again after a cancel or a delete.\n event.target.value = \"\";\n },\n [onPickFile]\n );\n\n const handleDrop = useCallback(\n (event: React.DragEvent): void => {\n event.preventDefault();\n event.stopPropagation();\n setDropping(false);\n\n const dropped = binaryFrom(event.dataTransfer);\n if (dropped) {\n onPickFile(dropped);\n }\n },\n [onPickFile]\n );\n\n const input = (\n <StyledHiddenFileInput\n ref={inputRef}\n type=\"file\"\n onChange={handleInputChange}\n />\n );\n\n if (element.file != null) {\n return (\n <>\n {input}\n <FileUploadCard\n element={element}\n selected={selected}\n resize={resize}\n onCancel={onCancel}\n onDelete={onDelete}\n />\n </>\n );\n }\n\n return (\n <>\n {input}\n <StyledFileCard selected={selected} aria-label=\"Empty file card\">\n <StackedCardRow\n role=\"custom\"\n bleed\n /* Marks this row as owning its own drops, so the board-level handler\n stands aside and lets the card take the file. */\n data-file-dropzone=\"\"\n onDragEnter={(event) => {\n event.preventDefault();\n setDropping(true);\n }}\n onDragOver={(event) => event.preventDefault()}\n onDragLeave={(event) => {\n // Ignore the leaves fired when crossing onto a child.\n if (!event.currentTarget.contains(event.relatedTarget as Node)) {\n setDropping(false);\n }\n }}\n onDrop={handleDrop}\n >\n <FilePlaceholder onClick={openPicker} />\n {dropping ? (\n <StyledDropOverlay>\n <span className=\"drop-box\">\n <Body2 color=\"secondary\">Drop here</Body2>\n </span>\n </StyledDropOverlay>\n ) : null}\n </StackedCardRow>\n </StyledFileCard>\n {selected ? (\n <FileFormattingToolbar\n status=\"placeholder\"\n onPick={openPicker}\n onDelete={onDelete}\n />\n ) : null}\n </>\n );\n};\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"fileElement.js","names":["React","useCallback","useEffect","useRef","useState","styled","StyledFormattingToolbar","StyledToolbarButton","stopClick","ArrowRefreshIcon","AttachmentIcon","CloseIcon","DownloadIcon","TrashIcon","UploadIcon","SpinnerLoader","ProgressRing","StackedCard","StackedCardCover","StackedCardRow","Tooltip","Body2","Caption1","Caption2","COVER_RATIO_IMAGE","Placeholder","FILE_DEFAULT_WIDTH","MAX_UPLOAD_BYTES","UPLOAD_TICK_MS","UPLOAD_STEP","PREPARING_MS","FILE_SIZE_UNITS","formatFileSize","value","_ref","unit","bytes","inUnit","toFixed","Math","trunc","describeFile","file","dot","name","lastIndexOf","hasExtension","base","slice","extension","size","mimeType","type","thumbnailUrl","startsWith","URL","createObjectURL","revokeThumbnail","revokeObjectURL","binaryFrom","data","files","length","item","Array","from","_data$items","items","kind","picked","getAsFile","useMockUpload","_useState","status","setStatus","_useState2","progress","setProgress","timers","ticker","progressRef","clearAll","current","forEach","clearTimeout","clearInterval","retry","push","setTimeout","setInterval","min","StyledFileCard","withConfig","displayName","componentId","StyledUploadCover","div","StyledFileFallback","StyledFileName","StyledDropOverlay","StyledHiddenFileInput","input","StyledPlaceholderBox","FilePlaceholder","props","createElement","_extends","icon","label","dashed","FileFormattingToolbar","_ref2","onPick","onCancel","onRetry","onDelete","onMouseDown","onClick","className","Fragment","title","FileUploadCard","_ref3","element","selected","resize","upload","ready","resizable","resizeAxis","resizeLabel","aspectRatio","renderFileThumbnail","radius","stroke","weight","color","style","cursor","role","src","alt","toUpperCase","FileElement","_ref4","autoOpen","onPickFile","inputRef","_useState3","dropping","setDropping","openPicker","_inputRef$current","click","handleInputChange","event","_event$target$files","target","handleDrop","preventDefault","stopPropagation","dropped","dataTransfer","ref","onChange","bleed","onDragEnter","onDragOver","onDragLeave","currentTarget","contains","relatedTarget","onDrop"],"sources":["../../../../src/presentation/whiteboard/fileElement.tsx"],"sourcesContent":["import React, {\n ReactElement,\n useCallback,\n useEffect,\n useRef,\n useState,\n} from \"react\";\n\nimport styled from \"styled-components\";\n\nimport {\n StyledFormattingToolbar,\n StyledToolbarButton,\n stopClick,\n} from \"./elements\";\nimport { CardResizeHandlers } from \"./linkElement\";\nimport {\n ArrowRefreshIcon,\n AttachmentIcon,\n CloseIcon,\n DownloadIcon,\n TrashIcon,\n UploadIcon,\n} from \"../../components/Icons\";\nimport { SpinnerLoader } from \"../../components/Loaders\";\nimport { ProgressRing } from \"../../components/ProgressRing\";\nimport {\n StackedCard,\n StackedCardCover,\n StackedCardRow,\n} from \"../../components/StackedCard\";\nimport { Tooltip } from \"../../components/Tooltip\";\nimport { Body2, Caption1, Caption2 } from \"../../components/Typography\";\nimport { COVER_RATIO_IMAGE, Placeholder } from \"../stackedCard/content\";\n\n/* ------------------------------------------------------------------ */\n/* File element — the upload lifecycle + the file card */\n/* ------------------------------------------------------------------ */\n\n/**\n * The file card is the second element built on `StackedCard`, and it mirrors the\n * card in a project's Files tab (`Folders/GridView/Items/File.js`): a thumbnail\n * over a strip with the name, then size · date.\n *\n * Its lifecycle is the app's real upload lifecycle, which is two phases and not\n * one — the distinction the ring alone doesn't tell you:\n *\n * uploading XHR progress 0–100. `ProgressRing radius={22} stroke={4}` with\n * the percentage, exactly as `Items/FileUpload.js` does it.\n * preparing bytes are in, the server is generating the thumbnail. Progress\n * is no longer knowable, so the ring gives way to the\n * indeterminate `SpinnerLoader` at the same size — again as the\n * real card does at `progress === 100`.\n * ready the thumbnail exists; the card renders it.\n * error the upload failed: retry, same as the app's `ArrowRefreshIcon`.\n *\n * Both phases reserve the same box as the finished cover, so a card never\n * reflows as it climbs — the discipline the unfurl ladder established.\n */\n\n/* The Files-tab card is a fixed 208×208. On a canvas the width is the host's,\n so 208 is only the default a click-placed card takes. */\nexport const FILE_DEFAULT_WIDTH = 208;\n\n/* Big enough to be worth refusing, so the error state is reachable: the server\n enforces the real limits (and answers StorageOverusedError when full). */\nexport const MAX_UPLOAD_BYTES = 25 * 1024 * 1024;\n\nexport const UPLOAD_TICK_MS = 110;\nexport const UPLOAD_STEP = 9;\n/* How long the server spends making a thumbnail once the bytes have landed. */\nexport const PREPARING_MS = 1100;\n\n/** What the mock keeps about a picked file. */\nexport interface PickedFile {\n /** Name without the extension — truncates on its own. */\n base: string;\n /** Extension without the dot; never truncated, as in the real card. */\n extension: string;\n size: number;\n mimeType: string;\n /** An object URL, so an image really renders. Null for everything else. */\n thumbnailUrl: string | null;\n}\n\n/** A file element on the board. Position lives in the shared positions map. */\nexport interface FileElementDef {\n id: string;\n width: number;\n /** null while the card is an empty placeholder waiting for a file. */\n file: PickedFile | null;\n}\n\n/* Angie.functions.format_file_size — two decimals, no space, lower-case k.\n \"1.20MB\", not \"1.2 MB\". Reproduced exactly so the mock reads like the app. */\nexport const FILE_SIZE_UNITS: [string, number][] = [\n [\"TB\", 1099511627776],\n [\"GB\", 1073741824],\n [\"MB\", 1048576],\n [\"kB\", 1024],\n];\n\nexport const formatFileSize = (value: number): string => {\n for (const [unit, bytes] of FILE_SIZE_UNITS) {\n const inUnit = value / bytes;\n if (inUnit > 0.9) {\n return `${inUnit.toFixed(2)}${unit}`;\n }\n }\n\n return `${Math.trunc(value)}B`;\n};\n\nexport const describeFile = (file: File): PickedFile => {\n const dot = file.name.lastIndexOf(\".\");\n const hasExtension = dot > 0;\n\n return {\n base: hasExtension ? file.name.slice(0, dot) : file.name,\n extension: hasExtension ? file.name.slice(dot + 1) : \"\",\n size: file.size,\n mimeType: file.type,\n // Images get a real thumbnail; the server would generate one for every type,\n // but the mock can only show what the browser can already decode.\n thumbnailUrl: file.type.startsWith(\"image/\")\n ? URL.createObjectURL(file)\n : null,\n };\n};\n\n/* Object URLs are a manual allocation — release one whenever the file it stands\n for stops being on the board. */\nexport const revokeThumbnail = (file: PickedFile | null): void => {\n if (file?.thumbnailUrl) {\n URL.revokeObjectURL(file.thumbnailUrl);\n }\n};\n\n/** The first actual file on a clipboard or a drop, or null if there is none. */\nexport const binaryFrom = (data: DataTransfer | null): File | null => {\n if (!data) {\n return null;\n }\n\n if (data.files && data.files.length > 0) {\n return data.files[0];\n }\n\n // A screenshot paste arrives as an item, not in `files`.\n for (const item of Array.from(data.items ?? [])) {\n if (item.kind === \"file\") {\n const picked = item.getAsFile();\n if (picked) {\n return picked;\n }\n }\n }\n\n return null;\n};\n\nexport type UploadStatus = \"uploading\" | \"preparing\" | \"ready\" | \"error\";\n\nexport interface UploadController {\n status: UploadStatus;\n /** 0–100, as the app's XHR reports it. Only meaningful while uploading. */\n progress: number;\n retry: () => void;\n}\n\n/**\n * Drives one file through the upload lifecycle. Stands in for\n * `useFileHandler` + the XHR in `utils/upload.jsx`: ticks progress to 100,\n * hands over to the thumbnail phase, then resolves.\n */\nexport const useMockUpload = (file: PickedFile | null): UploadController => {\n const [status, setStatus] = useState<UploadStatus>(\"uploading\");\n const [progress, setProgress] = useState(0);\n\n const timers = useRef<ReturnType<typeof setTimeout>[]>([]);\n const ticker = useRef<ReturnType<typeof setInterval> | null>(null);\n const progressRef = useRef(0);\n\n const clearAll = useCallback(() => {\n timers.current.forEach(clearTimeout);\n timers.current = [];\n if (ticker.current) {\n clearInterval(ticker.current);\n ticker.current = null;\n }\n }, []);\n\n const retry = useCallback(() => {\n clearAll();\n progressRef.current = 0;\n setProgress(0);\n setStatus(\"uploading\");\n\n if (!file) {\n return;\n }\n\n if (file.size > MAX_UPLOAD_BYTES) {\n timers.current.push(setTimeout(() => setStatus(\"error\"), 700));\n\n return;\n }\n\n ticker.current = setInterval(() => {\n progressRef.current = Math.min(100, progressRef.current + UPLOAD_STEP);\n setProgress(progressRef.current);\n\n if (progressRef.current >= 100) {\n clearAll();\n // The bytes are up; the thumbnail is the server's job now.\n setStatus(\"preparing\");\n timers.current.push(setTimeout(() => setStatus(\"ready\"), PREPARING_MS));\n }\n }, UPLOAD_TICK_MS);\n }, [clearAll, file]);\n\n useEffect(() => {\n retry();\n\n return clearAll;\n }, [retry, clearAll]);\n\n return { status, progress, retry };\n};\n\n/* The card fills the box the board drew; height stays auto. */\nexport const StyledFileCard = styled(StackedCard)`\n && {\n width: 100%;\n }\n\n user-select: none;\n`;\n\n/* The cover while uploading or preparing — the ring/spinner centred in the box\n the finished thumbnail will occupy, so resolving never reflows the card. */\nexport const StyledUploadCover = styled.div`\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 10px;\n width: 100%;\n height: 100%;\n background-color: var(--color-theme-200);\n`;\n\n/* No thumbnail (the browser can't decode a .zip): the clip plus the extension.\n The real card has NO type-icon fallback — it renders a bare <img> and trusts\n the server — so this is net-new and worth a decision. */\nexport const StyledFileFallback = styled.div`\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 8px;\n width: 100%;\n height: 100%;\n background-color: var(--color-theme-200);\n color: var(--color-theme-600);\n\n > svg {\n width: 36px;\n height: 36px;\n fill: var(--color-theme-500);\n }\n`;\n\n/* Name row: the base name truncates, the extension never does — the same split\n the real card makes with removeExtensionFromFileName. */\nexport const StyledFileName = styled.div`\n display: flex;\n align-items: baseline;\n min-width: 0;\n width: 100%;\n\n .file-base {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n .file-ext {\n flex-shrink: 0;\n }\n`;\n\n/* The drop overlay, from directive.ang_drop_files.less: a near-opaque cover\n with a 2px dashed primary border and \"Drop here\". The app sets 24px type for\n a full-page target; on a card it reads at Body2. */\nexport const StyledDropOverlay = styled.div`\n position: absolute;\n inset: 0;\n z-index: 3;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 8px;\n box-sizing: border-box;\n background-color: var(--page-paper-main);\n\n .drop-box {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 100%;\n height: 100%;\n box-sizing: border-box;\n border: 2px dashed var(--color-primary);\n border-radius: 6px;\n }\n`;\n\nexport const StyledHiddenFileInput = styled.input`\n display: none;\n`;\n\n/* The placeholder reserves the same box the finished cover will occupy — the\n cover's ratio, not a pixel height — so attaching a file does not resize the\n card under the pointer. Placeholder's own fixed height is overridden here;\n the descendant selector outranks its class. */\nexport const StyledPlaceholderBox = styled.div`\n width: 100%;\n aspect-ratio: ${COVER_RATIO_IMAGE};\n\n > button {\n height: 100%;\n }\n`;\n\n/* The interactive empty state, in the shared placeholder frame the other card\n types use. Doubles as the drop target, like its copy promises. */\nexport const FilePlaceholder = (\n props: React.ButtonHTMLAttributes<HTMLButtonElement>\n): ReactElement => (\n <StyledPlaceholderBox>\n {/* Fills the card, so it has to be draggable as well as clickable. */}\n <Placeholder\n icon={<AttachmentIcon />}\n label=\"Drop a file or click to upload\"\n dashed\n data-drag-through=\"\"\n {...props}\n />\n </StyledPlaceholderBox>\n);\n\nexport interface FileToolbarProps {\n status: UploadStatus | \"placeholder\";\n /* Each phase only supplies the actions its own buttons need. */\n onPick?: () => void;\n onCancel?: () => void;\n onRetry?: () => void;\n onDelete: () => void;\n}\n\n/* The file element's floating toolbar. The leading action is whatever the\n current phase makes meaningful; Move to Trash is always available. */\nexport const FileFormattingToolbar = ({\n status,\n onPick,\n onCancel,\n onRetry,\n onDelete,\n}: FileToolbarProps): ReactElement => (\n <StyledFormattingToolbar onMouseDown={stopClick} onClick={stopClick}>\n {status === \"placeholder\" ? (\n <StyledToolbarButton type=\"button\" onClick={onPick}>\n <UploadIcon className=\"i16\" />\n Upload\n </StyledToolbarButton>\n ) : null}\n {status === \"uploading\" || status === \"preparing\" ? (\n <StyledToolbarButton type=\"button\" onClick={onCancel}>\n <CloseIcon className=\"i16\" />\n Cancel\n </StyledToolbarButton>\n ) : null}\n {status === \"error\" ? (\n <>\n <StyledToolbarButton type=\"button\" onClick={onRetry}>\n <ArrowRefreshIcon className=\"i16\" />\n Retry\n </StyledToolbarButton>\n {/* A failed upload needs a way back to the placeholder too — otherwise\n a file that can never succeed leaves trashing the card as the only\n exit. */}\n <StyledToolbarButton type=\"button\" onClick={onCancel}>\n <CloseIcon className=\"i16\" />\n Cancel\n </StyledToolbarButton>\n </>\n ) : null}\n {/* Inert, like the board's other export-shaped actions — there is no real\n stored file behind a mock. */}\n {status === \"ready\" ? (\n <StyledToolbarButton type=\"button\">\n <DownloadIcon className=\"i16\" />\n Download\n </StyledToolbarButton>\n ) : null}\n <span className=\"divider\" />\n <Tooltip title=\"Move to Trash\">\n <StyledToolbarButton\n type=\"button\"\n className=\"icon-only\"\n onClick={onDelete}\n >\n <TrashIcon className=\"i16\" />\n </StyledToolbarButton>\n </Tooltip>\n </StyledFormattingToolbar>\n);\n\nexport interface FileUploadCardProps {\n element: FileElementDef;\n selected: boolean;\n resize: CardResizeHandlers;\n onCancel: () => void;\n onDelete: () => void;\n}\n\n/**\n * A file element with a file attached: the card runs the upload lifecycle and\n * then renders the finished preview.\n */\nexport const FileUploadCard = ({\n element,\n selected,\n resize,\n onCancel,\n onDelete,\n}: FileUploadCardProps): ReactElement => {\n const file = element.file;\n const upload = useMockUpload(file);\n const ready = upload.status === \"ready\";\n\n return (\n <>\n <StyledFileCard\n selected={selected}\n resizable={selected}\n resizeAxis=\"width\"\n resizeLabel=\"Resize file card\"\n {...resize}\n >\n <StackedCardCover aspectRatio={COVER_RATIO_IMAGE}>\n {ready ? (\n renderFileThumbnail(file)\n ) : (\n <StyledUploadCover>\n {/* Determinate while the bytes move, indeterminate once they have\n landed — the app's own switch at progress === 100. */}\n {upload.status === \"uploading\" ? (\n <ProgressRing progress={upload.progress} radius={22} stroke={4}>\n <Caption2 weight=\"bold\" color=\"secondary\">\n {upload.progress}%\n </Caption2>\n </ProgressRing>\n ) : null}\n {upload.status === \"preparing\" ? (\n <SpinnerLoader radius={22} stroke={4} />\n ) : null}\n {upload.status === \"error\" ? (\n <ArrowRefreshIcon\n style={{ cursor: \"pointer\" }}\n onClick={upload.retry}\n />\n ) : null}\n <Caption2 color=\"tertiary\">\n {upload.status === \"uploading\" ? \"Uploading…\" : null}\n {upload.status === \"preparing\" ? \"Preparing preview…\" : null}\n {upload.status === \"error\" ? \"Upload failed\" : null}\n </Caption2>\n </StyledUploadCover>\n )}\n </StackedCardCover>\n\n <StackedCardRow role=\"title\">\n <StyledFileName>\n <Caption1 weight=\"bold\" className=\"file-base\">\n {file?.base}\n </Caption1>\n {file?.extension ? (\n <Caption1 weight=\"bold\" className=\"file-ext\">\n .{file.extension}\n </Caption1>\n ) : null}\n </StyledFileName>\n </StackedCardRow>\n\n {/* The real card hides its metadata until hover (max-height 0 → 55px).\n On a canvas the card is the object, not a row in a dense grid, so the\n line stays up — but it only says anything once the file exists. */}\n <StackedCardRow role=\"meta\">\n <Caption2 color=\"tertiary\">\n {ready && file ? `${formatFileSize(file.size)} · Just now` : \" \"}\n </Caption2>\n </StackedCardRow>\n </StyledFileCard>\n {selected ? (\n <FileFormattingToolbar\n status={upload.status}\n onCancel={onCancel}\n onRetry={upload.retry}\n onDelete={onDelete}\n />\n ) : null}\n </>\n );\n};\n\n/* An image renders for real; anything else falls back to the clip + extension. */\nexport const renderFileThumbnail = (file: PickedFile | null): ReactElement =>\n file?.thumbnailUrl ? (\n <img src={file.thumbnailUrl} alt=\"\" />\n ) : (\n <StyledFileFallback>\n <AttachmentIcon />\n <Caption2 color=\"tertiary\">\n {file?.extension ? file.extension.toUpperCase() : \"FILE\"}\n </Caption2>\n </StyledFileFallback>\n );\n\nexport interface FileElementProps {\n element: FileElementDef;\n selected: boolean;\n /** Open the file picker as soon as a freshly drawn placeholder lands. */\n autoOpen: boolean;\n onPickFile: (file: File) => void;\n resize: CardResizeHandlers;\n onCancel: () => void;\n onDelete: () => void;\n}\n\n/**\n * The two shapes of a file element: an empty placeholder that can be clicked or\n * dropped onto, and the uploading/ready card.\n *\n * A box drawn with the File tool opens the picker immediately. Dismissing the\n * picker fires no change, so the card simply stays a placeholder — which is what\n * makes Esc a no-op by construction rather than by handling.\n */\nexport const FileElement = ({\n element,\n selected,\n autoOpen,\n onPickFile,\n resize,\n onCancel,\n onDelete,\n}: FileElementProps): ReactElement => {\n const inputRef = useRef<HTMLInputElement | null>(null);\n const [dropping, setDropping] = useState(false);\n\n const openPicker = useCallback(() => {\n inputRef.current?.click();\n }, []);\n\n useEffect(() => {\n if (autoOpen) {\n openPicker();\n }\n }, [autoOpen, openPicker]);\n\n const handleInputChange = useCallback(\n (event: React.ChangeEvent<HTMLInputElement>): void => {\n const picked = event.target.files?.[0];\n if (picked) {\n onPickFile(picked);\n }\n // Let the same file be chosen again after a cancel or a delete.\n event.target.value = \"\";\n },\n [onPickFile]\n );\n\n const handleDrop = useCallback(\n (event: React.DragEvent): void => {\n event.preventDefault();\n event.stopPropagation();\n setDropping(false);\n\n const dropped = binaryFrom(event.dataTransfer);\n if (dropped) {\n onPickFile(dropped);\n }\n },\n [onPickFile]\n );\n\n const input = (\n <StyledHiddenFileInput\n ref={inputRef}\n type=\"file\"\n onChange={handleInputChange}\n />\n );\n\n if (element.file != null) {\n return (\n <>\n {input}\n <FileUploadCard\n element={element}\n selected={selected}\n resize={resize}\n onCancel={onCancel}\n onDelete={onDelete}\n />\n </>\n );\n }\n\n return (\n <>\n {input}\n <StyledFileCard selected={selected} aria-label=\"Empty file card\">\n <StackedCardRow\n role=\"custom\"\n bleed\n /* Marks this row as owning its own drops, so the board-level handler\n stands aside and lets the card take the file. */\n data-file-dropzone=\"\"\n onDragEnter={(event) => {\n event.preventDefault();\n setDropping(true);\n }}\n onDragOver={(event) => event.preventDefault()}\n onDragLeave={(event) => {\n // Ignore the leaves fired when crossing onto a child.\n if (!event.currentTarget.contains(event.relatedTarget as Node)) {\n setDropping(false);\n }\n }}\n onDrop={handleDrop}\n >\n <FilePlaceholder onClick={openPicker} />\n {dropping ? (\n <StyledDropOverlay>\n <span className=\"drop-box\">\n <Body2 color=\"secondary\">Drop here</Body2>\n </span>\n </StyledDropOverlay>\n ) : null}\n </StackedCardRow>\n </StyledFileCard>\n {selected ? (\n <FileFormattingToolbar\n status=\"placeholder\"\n onPick={openPicker}\n onDelete={onDelete}\n />\n ) : null}\n </>\n );\n};\n"],"mappings":";AAAA,OAAOA,KAAK,IAEVC,WAAW,EACXC,SAAS,EACTC,MAAM,EACNC,QAAQ,QACH,OAAO;AAEd,OAAOC,MAAM,MAAM,mBAAmB;AAEtC,SACEC,uBAAuB,EACvBC,mBAAmB,EACnBC,SAAS,QACJ,YAAY;AAEnB,SACEC,gBAAgB,EAChBC,cAAc,EACdC,SAAS,EACTC,YAAY,EACZC,SAAS,EACTC,UAAU,QACL,wBAAwB;AAC/B,SAASC,aAAa,QAAQ,0BAA0B;AACxD,SAASC,YAAY,QAAQ,+BAA+B;AAC5D,SACEC,WAAW,EACXC,gBAAgB,EAChBC,cAAc,QACT,8BAA8B;AACrC,SAASC,OAAO,QAAQ,0BAA0B;AAClD,SAASC,KAAK,EAAEC,QAAQ,EAAEC,QAAQ,QAAQ,6BAA6B;AACvE,SAASC,iBAAiB,EAAEC,WAAW,QAAQ,wBAAwB;;AAEvE;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,OAAO,MAAMC,kBAAkB,GAAG,GAAG;;AAErC;AACA;AACA,OAAO,MAAMC,gBAAgB,GAAG,EAAE,GAAG,IAAI,GAAG,IAAI;AAEhD,OAAO,MAAMC,cAAc,GAAG,GAAG;AACjC,OAAO,MAAMC,WAAW,GAAG,CAAC;AAC5B;AACA,OAAO,MAAMC,YAAY,GAAG,IAAI;;AAEhC;;AAYA;;AAQA;AACA;AACA,OAAO,MAAMC,eAAmC,GAAG,CACjD,CAAC,IAAI,EAAE,aAAa,CAAC,EACrB,CAAC,IAAI,EAAE,UAAU,CAAC,EAClB,CAAC,IAAI,EAAE,OAAO,CAAC,EACf,CAAC,IAAI,EAAE,IAAI,CAAC,CACb;AAED,OAAO,MAAMC,cAAc,GAAIC,KAAa,IAAa;EACvD,WAAAC,IAAA,IAA4BH,eAAe,EAAE;IAAA,MAAjCI,IAAI,GAAAD,IAAA;IAAA,MAAEE,KAAK,GAAAF,IAAA;IACrB,MAAMG,MAAM,GAAGJ,KAAK,GAAGG,KAAK;IAC5B,IAAIC,MAAM,GAAG,GAAG,EAAE;MAChB,YAAUA,MAAM,CAACC,OAAO,CAAC,CAAC,CAAC,GAAGH,IAAI;IACpC;EACF;EAEA,OAAUI,IAAI,CAACC,KAAK,CAACP,KAAK,CAAC;AAC7B,CAAC;AAED,OAAO,MAAMQ,YAAY,GAAIC,IAAU,IAAiB;EACtD,MAAMC,GAAG,GAAGD,IAAI,CAACE,IAAI,CAACC,WAAW,CAAC,GAAG,CAAC;EACtC,MAAMC,YAAY,GAAGH,GAAG,GAAG,CAAC;EAE5B,OAAO;IACLI,IAAI,EAAED,YAAY,GAAGJ,IAAI,CAACE,IAAI,CAACI,KAAK,CAAC,CAAC,EAAEL,GAAG,CAAC,GAAGD,IAAI,CAACE,IAAI;IACxDK,SAAS,EAAEH,YAAY,GAAGJ,IAAI,CAACE,IAAI,CAACI,KAAK,CAACL,GAAG,GAAG,CAAC,CAAC,GAAG,EAAE;IACvDO,IAAI,EAAER,IAAI,CAACQ,IAAI;IACfC,QAAQ,EAAET,IAAI,CAACU,IAAI;IACnB;IACA;IACAC,YAAY,EAAEX,IAAI,CAACU,IAAI,CAACE,UAAU,CAAC,QAAQ,CAAC,GACxCC,GAAG,CAACC,eAAe,CAACd,IAAI,CAAC,GACzB;EACN,CAAC;AACH,CAAC;;AAED;AACA;AACA,OAAO,MAAMe,eAAe,GAAIf,IAAuB,IAAW;EAChE,IAAIA,IAAI,YAAJA,IAAI,CAAEW,YAAY,EAAE;IACtBE,GAAG,CAACG,eAAe,CAAChB,IAAI,CAACW,YAAY,CAAC;EACxC;AACF,CAAC;;AAED;AACA,OAAO,MAAMM,UAAU,GAAIC,IAAyB,IAAkB;EACpE,IAAI,CAACA,IAAI,EAAE;IACT,OAAO,IAAI;EACb;EAEA,IAAIA,IAAI,CAACC,KAAK,IAAID,IAAI,CAACC,KAAK,CAACC,MAAM,GAAG,CAAC,EAAE;IACvC,OAAOF,IAAI,CAACC,KAAK,CAAC,CAAC,CAAC;EACtB;;EAEA;EACA,KAAK,MAAME,IAAI,IAAIC,KAAK,CAACC,IAAI,EAAAC,WAAA,GAACN,IAAI,CAACO,KAAK,YAAAD,WAAA,GAAI,EAAE,CAAC,EAAE;IAAA,IAAAA,WAAA;IAC/C,IAAIH,IAAI,CAACK,IAAI,KAAK,MAAM,EAAE;MACxB,MAAMC,MAAM,GAAGN,IAAI,CAACO,SAAS,CAAC,CAAC;MAC/B,IAAID,MAAM,EAAE;QACV,OAAOA,MAAM;MACf;IACF;EACF;EAEA,OAAO,IAAI;AACb,CAAC;AAWD;AACA;AACA;AACA;AACA;AACA,OAAO,MAAME,aAAa,GAAI7B,IAAuB,IAAuB;EAC1E,MAAA8B,SAAA,GAA4BpE,QAAQ,CAAe,WAAW,CAAC;IAAxDqE,MAAM,GAAAD,SAAA;IAAEE,SAAS,GAAAF,SAAA;EACxB,MAAAG,UAAA,GAAgCvE,QAAQ,CAAC,CAAC,CAAC;IAApCwE,QAAQ,GAAAD,UAAA;IAAEE,WAAW,GAAAF,UAAA;EAE5B,MAAMG,MAAM,GAAG3E,MAAM,CAAkC,EAAE,CAAC;EAC1D,MAAM4E,MAAM,GAAG5E,MAAM,CAAwC,IAAI,CAAC;EAClE,MAAM6E,WAAW,GAAG7E,MAAM,CAAC,CAAC,CAAC;EAE7B,MAAM8E,QAAQ,GAAGhF,WAAW,CAAC,MAAM;IACjC6E,MAAM,CAACI,OAAO,CAACC,OAAO,CAACC,YAAY,CAAC;IACpCN,MAAM,CAACI,OAAO,GAAG,EAAE;IACnB,IAAIH,MAAM,CAACG,OAAO,EAAE;MAClBG,aAAa,CAACN,MAAM,CAACG,OAAO,CAAC;MAC7BH,MAAM,CAACG,OAAO,GAAG,IAAI;IACvB;EACF,CAAC,EAAE,EAAE,CAAC;EAEN,MAAMI,KAAK,GAAGrF,WAAW,CAAC,MAAM;IAC9BgF,QAAQ,CAAC,CAAC;IACVD,WAAW,CAACE,OAAO,GAAG,CAAC;IACvBL,WAAW,CAAC,CAAC,CAAC;IACdH,SAAS,CAAC,WAAW,CAAC;IAEtB,IAAI,CAAChC,IAAI,EAAE;MACT;IACF;IAEA,IAAIA,IAAI,CAACQ,IAAI,GAAGvB,gBAAgB,EAAE;MAChCmD,MAAM,CAACI,OAAO,CAACK,IAAI,CAACC,UAAU,CAAC,MAAMd,SAAS,CAAC,OAAO,CAAC,EAAE,GAAG,CAAC,CAAC;MAE9D;IACF;IAEAK,MAAM,CAACG,OAAO,GAAGO,WAAW,CAAC,MAAM;MACjCT,WAAW,CAACE,OAAO,GAAG3C,IAAI,CAACmD,GAAG,CAAC,GAAG,EAAEV,WAAW,CAACE,OAAO,GAAGrD,WAAW,CAAC;MACtEgD,WAAW,CAACG,WAAW,CAACE,OAAO,CAAC;MAEhC,IAAIF,WAAW,CAACE,OAAO,IAAI,GAAG,EAAE;QAC9BD,QAAQ,CAAC,CAAC;QACV;QACAP,SAAS,CAAC,WAAW,CAAC;QACtBI,MAAM,CAACI,OAAO,CAACK,IAAI,CAACC,UAAU,CAAC,MAAMd,SAAS,CAAC,OAAO,CAAC,EAAE5C,YAAY,CAAC,CAAC;MACzE;IACF,CAAC,EAAEF,cAAc,CAAC;EACpB,CAAC,EAAE,CAACqD,QAAQ,EAAEvC,IAAI,CAAC,CAAC;EAEpBxC,SAAS,CAAC,MAAM;IACdoF,KAAK,CAAC,CAAC;IAEP,OAAOL,QAAQ;EACjB,CAAC,EAAE,CAACK,KAAK,EAAEL,QAAQ,CAAC,CAAC;EAErB,OAAO;IAAER,MAAM;IAAEG,QAAQ;IAAEU;EAAM,CAAC;AACpC,CAAC;;AAED;AACA,OAAO,MAAMK,cAAc,GAAGtF,MAAM,CAACY,WAAW,CAAC,CAAA2E,UAAA;EAAAC,WAAA;EAAAC,WAAA;AAAA,wCAMhD;;AAED;AACA;AACA,OAAO,MAAMC,iBAAiB,GAAG1F,MAAM,CAAC2F,GAAG,CAAAJ,UAAA;EAAAC,WAAA;EAAAC,WAAA;AAAA,6JAS1C;;AAED;AACA;AACA;AACA,OAAO,MAAMG,kBAAkB,GAAG5F,MAAM,CAAC2F,GAAG,CAAAJ,UAAA;EAAAC,WAAA;EAAAC,WAAA;AAAA,mPAgB3C;;AAED;AACA;AACA,OAAO,MAAMI,cAAc,GAAG7F,MAAM,CAAC2F,GAAG,CAAAJ,UAAA;EAAAC,WAAA;EAAAC,WAAA;AAAA,gKAevC;;AAED;AACA;AACA;AACA,OAAO,MAAMK,iBAAiB,GAAG9F,MAAM,CAAC2F,GAAG,CAAAJ,UAAA;EAAAC,WAAA;EAAAC,WAAA;AAAA,qVAqB1C;AAED,OAAO,MAAMM,qBAAqB,GAAG/F,MAAM,CAACgG,KAAK,CAAAT,UAAA;EAAAC,WAAA;EAAAC,WAAA;AAAA,qBAEhD;;AAED;AACA;AACA;AACA;AACA,OAAO,MAAMQ,oBAAoB,GAAGjG,MAAM,CAAC2F,GAAG,CAAAJ,UAAA;EAAAC,WAAA;EAAAC,WAAA;AAAA,4DAE5BtE,iBAAiB,CAKlC;;AAED;AACA;AACA,OAAO,MAAM+E,eAAe,GAC1BC,KAAoD,iBAEpDxG,KAAA,CAAAyG,aAAA,CAACH,oBAAoB,qBAEnBtG,KAAA,CAAAyG,aAAA,CAAChF,WAAW,EAAAiF,QAAA;EACVC,IAAI,eAAE3G,KAAA,CAAAyG,aAAA,CAAC/F,cAAc,MAAE,CAAE;EACzBkG,KAAK,EAAC,gCAAgC;EACtCC,MAAM;EACN,qBAAkB;AAAE,GAChBL,KAAK,CACV,CACmB,CACvB;AAWD;AACA;AACA,OAAO,MAAMM,qBAAqB,GAAGC,KAAA;EAAA,IACnCtC,MAAM,GAAAsC,KAAA,CAANtC,MAAM;IACNuC,MAAM,GAAAD,KAAA,CAANC,MAAM;IACNC,QAAQ,GAAAF,KAAA,CAARE,QAAQ;IACRC,OAAO,GAAAH,KAAA,CAAPG,OAAO;IACPC,QAAQ,GAAAJ,KAAA,CAARI,QAAQ;EAAA,oBAERnH,KAAA,CAAAyG,aAAA,CAACnG,uBAAuB;IAAC8G,WAAW,EAAE5G,SAAU;IAAC6G,OAAO,EAAE7G;EAAU,GACjEiE,MAAM,KAAK,aAAa,gBACvBzE,KAAA,CAAAyG,aAAA,CAAClG,mBAAmB;IAAC6C,IAAI,EAAC,QAAQ;IAACiE,OAAO,EAAEL;EAAO,gBACjDhH,KAAA,CAAAyG,aAAA,CAAC3F,UAAU;IAACwG,SAAS,EAAC;EAAK,CAAE,CAAC,UAEX,CAAC,GACpB,IAAI,EACP7C,MAAM,KAAK,WAAW,IAAIA,MAAM,KAAK,WAAW,gBAC/CzE,KAAA,CAAAyG,aAAA,CAAClG,mBAAmB;IAAC6C,IAAI,EAAC,QAAQ;IAACiE,OAAO,EAAEJ;EAAS,gBACnDjH,KAAA,CAAAyG,aAAA,CAAC9F,SAAS;IAAC2G,SAAS,EAAC;EAAK,CAAE,CAAC,UAEV,CAAC,GACpB,IAAI,EACP7C,MAAM,KAAK,OAAO,gBACjBzE,KAAA,CAAAyG,aAAA,CAAAzG,KAAA,CAAAuH,QAAA,qBACEvH,KAAA,CAAAyG,aAAA,CAAClG,mBAAmB;IAAC6C,IAAI,EAAC,QAAQ;IAACiE,OAAO,EAAEH;EAAQ,gBAClDlH,KAAA,CAAAyG,aAAA,CAAChG,gBAAgB;IAAC6G,SAAS,EAAC;EAAK,CAAE,CAAC,SAEjB,CAAC,eAItBtH,KAAA,CAAAyG,aAAA,CAAClG,mBAAmB;IAAC6C,IAAI,EAAC,QAAQ;IAACiE,OAAO,EAAEJ;EAAS,gBACnDjH,KAAA,CAAAyG,aAAA,CAAC9F,SAAS;IAAC2G,SAAS,EAAC;EAAK,CAAE,CAAC,UAEV,CACrB,CAAC,GACD,IAAI,EAGP7C,MAAM,KAAK,OAAO,gBACjBzE,KAAA,CAAAyG,aAAA,CAAClG,mBAAmB;IAAC6C,IAAI,EAAC;EAAQ,gBAChCpD,KAAA,CAAAyG,aAAA,CAAC7F,YAAY;IAAC0G,SAAS,EAAC;EAAK,CAAE,CAAC,YAEb,CAAC,GACpB,IAAI,eACRtH,KAAA,CAAAyG,aAAA;IAAMa,SAAS,EAAC;EAAS,CAAE,CAAC,eAC5BtH,KAAA,CAAAyG,aAAA,CAACrF,OAAO;IAACoG,KAAK,EAAC;EAAe,gBAC5BxH,KAAA,CAAAyG,aAAA,CAAClG,mBAAmB;IAClB6C,IAAI,EAAC,QAAQ;IACbkE,SAAS,EAAC,WAAW;IACrBD,OAAO,EAAEF;EAAS,gBAElBnH,KAAA,CAAAyG,aAAA,CAAC5F,SAAS;IAACyG,SAAS,EAAC;EAAK,CAAE,CACT,CACd,CACc,CAAC;AAAA,CAC3B;AAUD;AACA;AACA;AACA;AACA,OAAO,MAAMG,cAAc,GAAGC,KAAA,IAMW;EAAA,IALvCC,OAAO,GAAAD,KAAA,CAAPC,OAAO;IACPC,QAAQ,GAAAF,KAAA,CAARE,QAAQ;IACRC,MAAM,GAAAH,KAAA,CAANG,MAAM;IACNZ,QAAQ,GAAAS,KAAA,CAART,QAAQ;IACRE,QAAQ,GAAAO,KAAA,CAARP,QAAQ;EAER,MAAMzE,IAAI,GAAGiF,OAAO,CAACjF,IAAI;EACzB,MAAMoF,MAAM,GAAGvD,aAAa,CAAC7B,IAAI,CAAC;EAClC,MAAMqF,KAAK,GAAGD,MAAM,CAACrD,MAAM,KAAK,OAAO;EAEvC,oBACEzE,KAAA,CAAAyG,aAAA,CAAAzG,KAAA,CAAAuH,QAAA,qBACEvH,KAAA,CAAAyG,aAAA,CAACd,cAAc,EAAAe,QAAA;IACbkB,QAAQ,EAAEA,QAAS;IACnBI,SAAS,EAAEJ,QAAS;IACpBK,UAAU,EAAC,OAAO;IAClBC,WAAW,EAAC;EAAkB,GAC1BL,MAAM,gBAEV7H,KAAA,CAAAyG,aAAA,CAACvF,gBAAgB;IAACiH,WAAW,EAAE3G;EAAkB,GAC9CuG,KAAK,GACJK,mBAAmB,CAAC1F,IAAI,CAAC,gBAEzB1C,KAAA,CAAAyG,aAAA,CAACV,iBAAiB,QAGf+B,MAAM,CAACrD,MAAM,KAAK,WAAW,gBAC5BzE,KAAA,CAAAyG,aAAA,CAACzF,YAAY;IAAC4D,QAAQ,EAAEkD,MAAM,CAAClD,QAAS;IAACyD,MAAM,EAAE,EAAG;IAACC,MAAM,EAAE;EAAE,gBAC7DtI,KAAA,CAAAyG,aAAA,CAAClF,QAAQ;IAACgH,MAAM,EAAC,MAAM;IAACC,KAAK,EAAC;EAAW,GACtCV,MAAM,CAAClD,QAAQ,EAAC,GACT,CACE,CAAC,GACb,IAAI,EACPkD,MAAM,CAACrD,MAAM,KAAK,WAAW,gBAC5BzE,KAAA,CAAAyG,aAAA,CAAC1F,aAAa;IAACsH,MAAM,EAAE,EAAG;IAACC,MAAM,EAAE;EAAE,CAAE,CAAC,GACtC,IAAI,EACPR,MAAM,CAACrD,MAAM,KAAK,OAAO,gBACxBzE,KAAA,CAAAyG,aAAA,CAAChG,gBAAgB;IACfgI,KAAK,EAAE;MAAEC,MAAM,EAAE;IAAU,CAAE;IAC7BrB,OAAO,EAAES,MAAM,CAACxC;EAAM,CACvB,CAAC,GACA,IAAI,eACRtF,KAAA,CAAAyG,aAAA,CAAClF,QAAQ;IAACiH,KAAK,EAAC;EAAU,GACvBV,MAAM,CAACrD,MAAM,KAAK,WAAW,GAAG,YAAY,GAAG,IAAI,EACnDqD,MAAM,CAACrD,MAAM,KAAK,WAAW,GAAG,oBAAoB,GAAG,IAAI,EAC3DqD,MAAM,CAACrD,MAAM,KAAK,OAAO,GAAG,eAAe,GAAG,IACvC,CACO,CAEL,CAAC,eAEnBzE,KAAA,CAAAyG,aAAA,CAACtF,cAAc;IAACwH,IAAI,EAAC;EAAO,gBAC1B3I,KAAA,CAAAyG,aAAA,CAACP,cAAc,qBACblG,KAAA,CAAAyG,aAAA,CAACnF,QAAQ;IAACiH,MAAM,EAAC,MAAM;IAACjB,SAAS,EAAC;EAAW,GAC1C5E,IAAI,oBAAJA,IAAI,CAAEK,IACC,CAAC,EACVL,IAAI,YAAJA,IAAI,CAAEO,SAAS,gBACdjD,KAAA,CAAAyG,aAAA,CAACnF,QAAQ;IAACiH,MAAM,EAAC,MAAM;IAACjB,SAAS,EAAC;EAAU,GAAC,GAC1C,EAAC5E,IAAI,CAACO,SACC,CAAC,GACT,IACU,CACF,CAAC,eAKjBjD,KAAA,CAAAyG,aAAA,CAACtF,cAAc;IAACwH,IAAI,EAAC;EAAM,gBACzB3I,KAAA,CAAAyG,aAAA,CAAClF,QAAQ;IAACiH,KAAK,EAAC;EAAU,GACvBT,KAAK,IAAIrF,IAAI,GAAMV,cAAc,CAACU,IAAI,CAACQ,IAAI,CAAC,sBAAgB,GACrD,CACI,CACF,CAAC,EAChB0E,QAAQ,gBACP5H,KAAA,CAAAyG,aAAA,CAACK,qBAAqB;IACpBrC,MAAM,EAAEqD,MAAM,CAACrD,MAAO;IACtBwC,QAAQ,EAAEA,QAAS;IACnBC,OAAO,EAAEY,MAAM,CAACxC,KAAM;IACtB6B,QAAQ,EAAEA;EAAS,CACpB,CAAC,GACA,IACJ,CAAC;AAEP,CAAC;;AAED;AACA,OAAO,MAAMiB,mBAAmB,GAAI1F,IAAuB,IACzDA,IAAI,YAAJA,IAAI,CAAEW,YAAY,gBAChBrD,KAAA,CAAAyG,aAAA;EAAKmC,GAAG,EAAElG,IAAI,CAACW,YAAa;EAACwF,GAAG,EAAC;AAAE,CAAE,CAAC,gBAEtC7I,KAAA,CAAAyG,aAAA,CAACR,kBAAkB,qBACjBjG,KAAA,CAAAyG,aAAA,CAAC/F,cAAc,MAAE,CAAC,eAClBV,KAAA,CAAAyG,aAAA,CAAClF,QAAQ;EAACiH,KAAK,EAAC;AAAU,GACvB9F,IAAI,YAAJA,IAAI,CAAEO,SAAS,GAAGP,IAAI,CAACO,SAAS,CAAC6F,WAAW,CAAC,CAAC,GAAG,MAC1C,CACQ,CACrB;AAaH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,MAAMC,WAAW,GAAGC,KAAA,IAQW;EAAA,IAPpCrB,OAAO,GAAAqB,KAAA,CAAPrB,OAAO;IACPC,QAAQ,GAAAoB,KAAA,CAARpB,QAAQ;IACRqB,QAAQ,GAAAD,KAAA,CAARC,QAAQ;IACRC,UAAU,GAAAF,KAAA,CAAVE,UAAU;IACVrB,MAAM,GAAAmB,KAAA,CAANnB,MAAM;IACNZ,QAAQ,GAAA+B,KAAA,CAAR/B,QAAQ;IACRE,QAAQ,GAAA6B,KAAA,CAAR7B,QAAQ;EAER,MAAMgC,QAAQ,GAAGhJ,MAAM,CAA0B,IAAI,CAAC;EACtD,MAAAiJ,UAAA,GAAgChJ,QAAQ,CAAC,KAAK,CAAC;IAAxCiJ,QAAQ,GAAAD,UAAA;IAAEE,WAAW,GAAAF,UAAA;EAE5B,MAAMG,UAAU,GAAGtJ,WAAW,CAAC,MAAM;IAAA,IAAAuJ,iBAAA;IACnC,CAAAA,iBAAA,GAAAL,QAAQ,CAACjE,OAAO,aAAhBsE,iBAAA,CAAkBC,KAAK,CAAC,CAAC;EAC3B,CAAC,EAAE,EAAE,CAAC;EAENvJ,SAAS,CAAC,MAAM;IACd,IAAI+I,QAAQ,EAAE;MACZM,UAAU,CAAC,CAAC;IACd;EACF,CAAC,EAAE,CAACN,QAAQ,EAAEM,UAAU,CAAC,CAAC;EAE1B,MAAMG,iBAAiB,GAAGzJ,WAAW,CAClC0J,KAA0C,IAAW;IAAA,IAAAC,mBAAA;IACpD,MAAMvF,MAAM,IAAAuF,mBAAA,GAAGD,KAAK,CAACE,MAAM,CAAChG,KAAK,qBAAlB+F,mBAAA,CAAqB,CAAC,CAAC;IACtC,IAAIvF,MAAM,EAAE;MACV6E,UAAU,CAAC7E,MAAM,CAAC;IACpB;IACA;IACAsF,KAAK,CAACE,MAAM,CAAC5H,KAAK,GAAG,EAAE;EACzB,CAAC,EACD,CAACiH,UAAU,CACb,CAAC;EAED,MAAMY,UAAU,GAAG7J,WAAW,CAC3B0J,KAAsB,IAAW;IAChCA,KAAK,CAACI,cAAc,CAAC,CAAC;IACtBJ,KAAK,CAACK,eAAe,CAAC,CAAC;IACvBV,WAAW,CAAC,KAAK,CAAC;IAElB,MAAMW,OAAO,GAAGtG,UAAU,CAACgG,KAAK,CAACO,YAAY,CAAC;IAC9C,IAAID,OAAO,EAAE;MACXf,UAAU,CAACe,OAAO,CAAC;IACrB;EACF,CAAC,EACD,CAACf,UAAU,CACb,CAAC;EAED,MAAM7C,KAAK,gBACTrG,KAAA,CAAAyG,aAAA,CAACL,qBAAqB;IACpB+D,GAAG,EAAEhB,QAAS;IACd/F,IAAI,EAAC,MAAM;IACXgH,QAAQ,EAAEV;EAAkB,CAC7B,CACF;EAED,IAAI/B,OAAO,CAACjF,IAAI,IAAI,IAAI,EAAE;IACxB,oBACE1C,KAAA,CAAAyG,aAAA,CAAAzG,KAAA,CAAAuH,QAAA,QACGlB,KAAK,eACNrG,KAAA,CAAAyG,aAAA,CAACgB,cAAc;MACbE,OAAO,EAAEA,OAAQ;MACjBC,QAAQ,EAAEA,QAAS;MACnBC,MAAM,EAAEA,MAAO;MACfZ,QAAQ,EAAEA,QAAS;MACnBE,QAAQ,EAAEA;IAAS,CACpB,CACD,CAAC;EAEP;EAEA,oBACEnH,KAAA,CAAAyG,aAAA,CAAAzG,KAAA,CAAAuH,QAAA,QACGlB,KAAK,eACNrG,KAAA,CAAAyG,aAAA,CAACd,cAAc;IAACiC,QAAQ,EAAEA,QAAS;IAAC,cAAW;EAAiB,gBAC9D5H,KAAA,CAAAyG,aAAA,CAACtF,cAAc;IACbwH,IAAI,EAAC,QAAQ;IACb0B,KAAK;IACL;AACV,uDADU;IAEA,sBAAmB,EAAE;IACrBC,WAAW,EAAGX,KAAK,IAAK;MACtBA,KAAK,CAACI,cAAc,CAAC,CAAC;MACtBT,WAAW,CAAC,IAAI,CAAC;IACnB,CAAE;IACFiB,UAAU,EAAGZ,KAAK,IAAKA,KAAK,CAACI,cAAc,CAAC,CAAE;IAC9CS,WAAW,EAAGb,KAAK,IAAK;MACtB;MACA,IAAI,CAACA,KAAK,CAACc,aAAa,CAACC,QAAQ,CAACf,KAAK,CAACgB,aAAqB,CAAC,EAAE;QAC9DrB,WAAW,CAAC,KAAK,CAAC;MACpB;IACF,CAAE;IACFsB,MAAM,EAAEd;EAAW,gBAEnB9J,KAAA,CAAAyG,aAAA,CAACF,eAAe;IAACc,OAAO,EAAEkC;EAAW,CAAE,CAAC,EACvCF,QAAQ,gBACPrJ,KAAA,CAAAyG,aAAA,CAACN,iBAAiB,qBAChBnG,KAAA,CAAAyG,aAAA;IAAMa,SAAS,EAAC;EAAU,gBACxBtH,KAAA,CAAAyG,aAAA,CAACpF,KAAK;IAACmH,KAAK,EAAC;EAAW,GAAC,WAAgB,CACrC,CACW,CAAC,GAClB,IACU,CACF,CAAC,EAChBZ,QAAQ,gBACP5H,KAAA,CAAAyG,aAAA,CAACK,qBAAqB;IACpBrC,MAAM,EAAC,aAAa;IACpBuC,MAAM,EAAEuC,UAAW;IACnBpC,QAAQ,EAAEA;EAAS,CACpB,CAAC,GACA,IACJ,CAAC;AAEP,CAAC","ignoreList":[]}
@@ -10,7 +10,7 @@ import { ChooseV2 } from "../../components/ChooseV2";
10
10
  import { Dot } from "../../components/Dot";
11
11
  import { EditableText } from "../../components/EditableText";
12
12
  import { IconButton } from "../../components/IconButton";
13
- import { AttachmentIcon, CircleSlashIcon, InsertLinkIcon, LockIcon, NoteIcon, PersonIcon, ProjectIcon, TaskIcon } from "../../components/Icons";
13
+ import { AttachmentIcon, CircleSlashIcon, InsertLinkIcon, LockIcon, FolderOutlineIcon, PersonIcon, StickyIcon, TaskIcon } from "../../components/Icons";
14
14
  import { Input, InputAdornment, InputNumber } from "../../components/Input";
15
15
  import { Label } from "../../components/Label";
16
16
  import { Select } from "../../components/Select";
@@ -547,7 +547,7 @@ export const RightInspector = _ref6 => {
547
547
  /* A limited card gets a NEUTRAL icon. The task and project glyphs would
548
548
  each say which kind of record is behind the card, and the kind is
549
549
  part of what the viewer is not entitled to. */
550
- limited ? /*#__PURE__*/React.createElement(LockIcon, null) : projectDef.kind === "person" ? /*#__PURE__*/React.createElement(PersonIcon, null) : projectDef.kind === "project" ? /*#__PURE__*/React.createElement(ProjectIcon, null) : /*#__PURE__*/React.createElement(TaskIcon, null), projectElementTitle(projectDef), projectDef.id, /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(StyledPropGroup, null, renderLocked(projectDef.id, cardTraits.readOnly)), cardTraits.geometry ? renderCardGeometry(projectDef.id, projectDef.width, width => setProjectElements(current => current.map(entry => {
550
+ limited ? /*#__PURE__*/React.createElement(LockIcon, null) : projectDef.kind === "person" ? /*#__PURE__*/React.createElement(PersonIcon, null) : projectDef.kind === "project" ? /*#__PURE__*/React.createElement(FolderOutlineIcon, null) : /*#__PURE__*/React.createElement(TaskIcon, null), projectElementTitle(projectDef), projectDef.id, /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(StyledPropGroup, null, renderLocked(projectDef.id, cardTraits.readOnly)), cardTraits.geometry ? renderCardGeometry(projectDef.id, projectDef.width, width => setProjectElements(current => current.map(entry => {
551
551
  if (entry.id !== projectDef.id) {
552
552
  return entry;
553
553
  }
@@ -676,7 +676,7 @@ export const RightInspector = _ref6 => {
676
676
  }));
677
677
  }
678
678
  };
679
- return shell(renderInspectorBody(shape ? SHAPE_TYPE_ICON[shape.type] : /*#__PURE__*/React.createElement(NoteIcon, null), name, def.id, /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(StyledPropGroup, null, renderBody(def.id), shape ? /*#__PURE__*/React.createElement(StyledPropRow, null, /*#__PURE__*/React.createElement(Label, {
679
+ return shell(renderInspectorBody(shape ? SHAPE_TYPE_ICON[shape.type] : /*#__PURE__*/React.createElement(StickyIcon, null), name, def.id, /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(StyledPropGroup, null, renderBody(def.id), shape ? /*#__PURE__*/React.createElement(StyledPropRow, null, /*#__PURE__*/React.createElement(Label, {
680
680
  size: "small",
681
681
  weight: "regular"
682
682
  }, "Shape"), /*#__PURE__*/React.createElement(OptionSelect, {