@aglyn/besigner-ui 1.0.0-beta.231 → 1.0.0-beta.232

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 (28) hide show
  1. package/package.json +19 -18
  2. package/src/lib/components/aside-panel.component.js +30 -3
  3. package/src/lib/components/aside-panel.component.js.map +1 -1
  4. package/src/lib/components/besigner-dnd-context.component.js +31 -2
  5. package/src/lib/components/besigner-dnd-context.component.js.map +1 -1
  6. package/src/lib/components/component-accordion-list.js +4 -2
  7. package/src/lib/components/component-accordion-list.js.map +1 -1
  8. package/src/lib/components/component-picker.js +42 -2
  9. package/src/lib/components/component-picker.js.map +1 -1
  10. package/src/lib/components/device-preview-controls.component.d.ts +2 -0
  11. package/src/lib/components/device-preview-controls.component.js +11 -5
  12. package/src/lib/components/device-preview-controls.component.js.map +1 -1
  13. package/src/lib/components/dnd/draggable-droppable.js +39 -0
  14. package/src/lib/components/dnd/draggable-droppable.js.map +1 -1
  15. package/src/lib/components/node-quick-actions.js +210 -174
  16. package/src/lib/components/node-quick-actions.js.map +1 -1
  17. package/src/lib/components/node-tree-view.js +11 -1
  18. package/src/lib/components/node-tree-view.js.map +1 -1
  19. package/src/lib/components/panel-controls.component.d.ts +6 -0
  20. package/src/lib/components/panel-controls.component.js +10 -6
  21. package/src/lib/components/panel-controls.component.js.map +1 -1
  22. package/src/lib/components/viewport-canvas.component.js +8 -0
  23. package/src/lib/components/viewport-canvas.component.js.map +1 -1
  24. package/src/lib/components/workspace-editor.component.js +131 -16
  25. package/src/lib/components/workspace-editor.component.js.map +1 -1
  26. package/src/lib/components/workspace-panel.component.d.ts +18 -0
  27. package/src/lib/components/workspace-panel.component.js +53 -3
  28. package/src/lib/components/workspace-panel.component.js.map +1 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aglyn/besigner-ui",
3
- "version": "1.0.0-beta.231",
3
+ "version": "1.0.0-beta.232",
4
4
  "license": "Apache-2.0",
5
5
  "homepage": "https://aglyn.com",
6
6
  "repository": {
@@ -25,22 +25,22 @@
25
25
  "./package.json": "./package.json"
26
26
  },
27
27
  "dependencies": {
28
- "@aglyn/aglyn": "1.0.0-beta.231",
29
- "@aglyn/aglyn-markdown-editor": "1.0.0-beta.231",
30
- "@aglyn/aglyn-node-renderer": "1.0.0-beta.231",
31
- "@aglyn/besigner": "1.0.0-beta.231",
32
- "@aglyn/shared-data-enums": "1.0.0-beta.231",
33
- "@aglyn/shared-data-mdi": "1.0.0-beta.231",
34
- "@aglyn/shared-data-types": "1.0.0-beta.231",
35
- "@aglyn/shared-svg-icons": "1.0.0-beta.231",
36
- "@aglyn/shared-ui-json-editor": "1.0.0-beta.231",
37
- "@aglyn/shared-ui-jsx": "1.0.0-beta.231",
38
- "@aglyn/shared-ui-jsx-forms": "1.0.0-beta.231",
39
- "@aglyn/shared-ui-snackstack": "1.0.0-beta.231",
40
- "@aglyn/shared-ui-theme": "1.0.0-beta.231",
41
- "@aglyn/shared-util-dom": "1.0.0-beta.231",
42
- "@aglyn/shared-util-tools": "1.0.0-beta.231",
43
- "@aglyn/shared-util-vendor": "1.0.0-beta.231",
28
+ "@aglyn/aglyn": "1.0.0-beta.232",
29
+ "@aglyn/aglyn-markdown-editor": "1.0.0-beta.232",
30
+ "@aglyn/aglyn-node-renderer": "1.0.0-beta.232",
31
+ "@aglyn/besigner": "1.0.0-beta.232",
32
+ "@aglyn/shared-data-enums": "1.0.0-beta.232",
33
+ "@aglyn/shared-data-mdi": "1.0.0-beta.232",
34
+ "@aglyn/shared-data-types": "1.0.0-beta.232",
35
+ "@aglyn/shared-svg-icons": "1.0.0-beta.232",
36
+ "@aglyn/shared-ui-json-editor": "1.0.0-beta.232",
37
+ "@aglyn/shared-ui-jsx": "1.0.0-beta.232",
38
+ "@aglyn/shared-ui-jsx-forms": "1.0.0-beta.232",
39
+ "@aglyn/shared-ui-snackstack": "1.0.0-beta.232",
40
+ "@aglyn/shared-ui-theme": "1.0.0-beta.232",
41
+ "@aglyn/shared-util-dom": "1.0.0-beta.232",
42
+ "@aglyn/shared-util-tools": "1.0.0-beta.232",
43
+ "@aglyn/shared-util-vendor": "1.0.0-beta.232",
44
44
  "@dnd-kit/core": "^6.3.1",
45
45
  "@dnd-kit/utilities": "^3.2.2",
46
46
  "@react-aria/utils": "^3.34.1",
@@ -64,7 +64,8 @@
64
64
  "@mui/system": "^9.2.0",
65
65
  "firebase": "^12.18.0",
66
66
  "next": "^16.3.3",
67
- "react": "^19.2.8"
67
+ "react": "^19.2.8",
68
+ "react-dom": "^19.2.8"
68
69
  },
69
70
  "sideEffects": false,
70
71
  "types": "./src/index.d.ts",
@@ -25,7 +25,7 @@ import { styled } from "@aglyn/shared-ui-theme";
25
25
  import { getDisplayName, numberFromHexadecimal, numberToHexadecimal } from "@aglyn/shared-util-tools";
26
26
  import { hoistNonReactStatics } from "@aglyn/shared-util-vendor";
27
27
  import { TabContext as MuiTabContext, TabList as MuiTabList, TabPanel as MuiTabPanel } from "@mui/lab";
28
- import { AppBar as MuiAppBar, Box, Button, Chip, Stack, Tab as MuiTab, Typography } from "@mui/material";
28
+ import { AppBar as MuiAppBar, Box, Button, Chip, Stack, Tab as MuiTab, Typography, useMediaQuery, useTheme } from "@mui/material";
29
29
  import { observer } from "mobx-react-lite";
30
30
  import { forwardRef, useCallback, useEffect } from "react";
31
31
  import useAddElementDrawerCallback from "../hooks/use-add-element-drawer-callback.js";
@@ -461,6 +461,27 @@ export const AsidePanelComponent = /*#__PURE__*/ forwardRef((props, ref)=>{
461
461
  ]), { defaultTab, tabs } = _panelTabs_panelKey;
462
462
  const { toggled, tab, size } = panel || {};
463
463
  const value = tab || defaultTab;
464
+ // Below `md` there is no room for a docked panel beside the canvas, so
465
+ // the panel overlays it as a temporary drawer instead (AGL-3599): from
466
+ // its own side on a tablet, and as a bottom sheet on a phone, where a
467
+ // side drawer would leave a sliver of canvas nobody can use.
468
+ const theme = useTheme();
469
+ const compact = useMediaQuery(theme.breakpoints.down('md'), {
470
+ noSsr: true
471
+ });
472
+ const phone = useMediaQuery(theme.breakpoints.down('sm'), {
473
+ noSsr: true
474
+ });
475
+ const handleClose = useCallback(()=>setPanel((prev)=>_extends({}, prev, {
476
+ toggled: false
477
+ })), [
478
+ setPanel
479
+ ]);
480
+ const handleOpen = useCallback(()=>setPanel((prev)=>_extends({}, prev, {
481
+ toggled: true
482
+ })), [
483
+ setPanel
484
+ ]);
464
485
  // The bottom-right corner belongs to this panel while it is open
465
486
  // (AGL-2486), so publish how far a viewport-fixed affordance has to
466
487
  // stand off to clear it. A console-dock launcher reads this; the console's
@@ -476,7 +497,9 @@ export const AsidePanelComponent = /*#__PURE__*/ forwardRef((props, ref)=>{
476
497
  // parsed rather than added to: `'375' + 20` is `'37520'`, which is a
477
498
  // perfectly valid CSS length and would park the launcher off-screen.
478
499
  const panelWidth = Number.parseFloat(String(size != null ? size : ''));
479
- const rightInset = panelKey === 'panelRight' && toggled && Number.isFinite(panelWidth) ? panelWidth + 20 : null;
500
+ // An overlaying drawer owns no corner: it is dismissed before anything
501
+ // under it is reached.
502
+ const rightInset = panelKey === 'panelRight' && toggled && !compact && Number.isFinite(panelWidth) ? panelWidth + 20 : null;
480
503
  useEffect(()=>{
481
504
  if (panelKey !== 'panelRight') return undefined;
482
505
  const root = document.documentElement;
@@ -506,7 +529,11 @@ export const AsidePanelComponent = /*#__PURE__*/ forwardRef((props, ref)=>{
506
529
  "aria-label": "left toolbox panel",
507
530
  size: size,
508
531
  open: toggled,
509
- component: "aside"
532
+ component: "aside",
533
+ temporary: compact,
534
+ temporaryAnchor: phone ? 'bottom' : undefined,
535
+ onClose: handleClose,
536
+ onOpen: handleOpen
510
537
  }, panelProps, rest, {
511
538
  children: [
512
539
  /*#__PURE__*/ _jsxs(MuiTabContext, {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../../libs/besigner/feature/designer/src/lib/components/aside-panel.component.tsx"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { canvas, NODE_ROOT_ID } from '@aglyn/aglyn'\nimport * as Besigner from '@aglyn/besigner'\nimport {\n type BesignerPanelKey,\n BesignerPanelTabFlag,\n} from '@aglyn/besigner'\nimport {\n ICON_VARIANT_ELEMENT,\n ICON_VARIANT_ELEMENT_BROWSE,\n ICON_VARIANT_ELEMENT_INTERACTIONS,\n ICON_VARIANT_ELEMENT_PROPERTIES,\n ICON_VARIANT_ELEMENT_STYLES,\n ICON_VARIANT_ELEMENT_TREE_VIEW,\n ICON_VARIANT_MODIFY_ADD,\n} from '@aglyn/shared-data-enums'\nimport { HelpTip, MdiIcon } from '@aglyn/shared-ui-jsx'\nimport { mergeSxProps, styled } from '@aglyn/shared-ui-theme'\nimport {\n getDisplayName,\n numberFromHexadecimal,\n numberToHexadecimal,\n} from '@aglyn/shared-util-tools'\nimport { hoistNonReactStatics } from '@aglyn/shared-util-vendor'\nimport {\n TabContext as MuiTabContext,\n TabList as MuiTabList,\n TabPanel as MuiTabPanel,\n type TabPanelProps as MuiTabPanelProps,\n} from '@mui/lab'\nimport {\n AppBar as MuiAppBar,\n Box,\n Button,\n Chip,\n Stack,\n Tab as MuiTab,\n Typography,\n} from '@mui/material'\nimport { observer } from 'mobx-react-lite'\nimport {\n type ComponentType,\n forwardRef,\n type SyntheticEvent,\n useCallback,\n useEffect,\n useMemo,\n useState,\n} from 'react'\nimport useAddElementDrawerCallback from '../hooks/use-add-element-drawer-callback'\nimport useAglynBesignerPanel from '../hooks/use-aglyn-besigner-panel'\nimport AccordionListComponent from './accordion-list.component'\nimport ElementInteractionsForm from './element-interactions-form.component'\nimport ComponentAccordionList from './component-accordion-list'\nimport ElementPropsForm from './element-props-form.component'\nimport ElementStylesForm from './element-styles-form.component'\nimport NodeTreeView, { type NodeTreeViewProps } from './node-tree-view'\nimport SiteThemeColorTokensProvider from './site-theme-color-tokens-provider.component'\nimport { usePublishActiveHostTheme } from '../utils/active-host-theme'\nimport { besignerInspected } from '../contexts/inspected-selection'\nimport {\n type LayoutElementSelection,\n layoutStyleSelection,\n} from '../contexts/layout-style-selection'\nimport {\n inspectorExtrasFor,\n useBesignerInspectorExtras,\n} from '../contexts/inspector-extras-context'\nimport { besignerDocsUrl } from '../utils/docs-help'\nimport WorkspacePanelComponent, {\n type WorkspacePanelComponentProps,\n} from './workspace-panel.component'\n\nconst TabPanel = styled(MuiTabPanel, {\n name: 'AglynTabPanel',\n})<MuiTabPanelProps>({\n padding: 0,\n overflow: 'auto',\n height: '100%',\n})\nconst TabPanelInner = styled('div', {\n name: 'AglynTabPanelInner',\n})(({ theme }) => ({\n width: '100%',\n}))\n\nconst emptyView = (\n <Stack\n direction=\"column\"\n component={TabPanelInner}\n sx={{\n justifyContent: 'center',\n height: 1,\n p: 2,\n }}\n >\n <Typography\n color=\"textSecondary\"\n variant=\"overline\"\n component=\"div\"\n align=\"center\"\n >\n <MdiIcon\n sx={{ opacity: 0.3, fontSize: 80 }}\n path={ICON_VARIANT_ELEMENT.path}\n />\n <div>{'Select an element'}</div>\n </Typography>\n </Stack>\n)\n\n\n/**\n * `Hero · Section` with a `SELECTED` tag — the inspector header the\n * `/product` hero mockup shows (AGL-2175).\n *\n * The right panel had no header at all: three tabs of controls with\n * nothing naming what they act on. On a canvas where clicking a child\n * moves the selection under you, that is the difference between editing\n * the section and editing the heading inside it — and the panel looked\n * identical either way.\n *\n * The second half is the COMPONENT, not a category: `labelShort` is the\n * preset's name (`Hero`) and the schema's is what it actually is\n * (`Section`). They are the same word often enough that it is dropped\n * when it would only repeat itself.\n */\nconst SelectedNodeHeader = observer(\n ({ node }: { node: Besigner.LastSelectedNode }) => {\n const name = node?.labelShort ?? ''\n const component = (node as { componentSchema?: { displayName?: string } })\n ?.componentSchema?.displayName\n const subtitle =\n component && component.toLowerCase() !== name.toLowerCase()\n ? `${name} · ${component}`\n : name\n return (\n <Stack\n direction=\"row\"\n spacing={1}\n sx={{\n alignItems: 'center',\n px: 2,\n py: 1,\n borderBottom: 1,\n borderColor: 'divider',\n }}\n >\n <Typography variant=\"subtitle2\" noWrap sx={{ flex: 1, minWidth: 0 }}>\n {subtitle || 'Element'}\n </Typography>\n <Chip\n size=\"small\"\n variant=\"outlined\"\n color=\"secondary\"\n label=\"SELECTED\"\n sx={{ height: 18, '& .MuiChip-label': { px: 0.75, fontSize: 10 } }}\n />\n </Stack>\n )\n },\n)\nSelectedNodeHeader.displayName = 'SelectedNodeHeader'\n\n/**\n * The panel while a shared-layout element is the target (AGL-3286): named in\n * the header like any selection, and marked as the layout's, styles only.\n */\nconst LayoutElementHeader = ({\n selection,\n}: {\n selection: LayoutElementSelection\n}) => (\n <Stack\n direction=\"row\"\n spacing={1}\n sx={{\n alignItems: 'center',\n px: 2,\n py: 1,\n borderBottom: 1,\n borderColor: 'divider',\n }}\n >\n <Typography variant=\"subtitle2\" noWrap sx={{ flex: 1, minWidth: 0 }}>\n {`${selection.label} · Layout`}\n </Typography>\n <Chip\n size=\"small\"\n variant=\"outlined\"\n color=\"info\"\n label=\"STYLES ONLY\"\n sx={{ height: 18, '& .MuiChip-label': { px: 0.75, fontSize: 10 } }}\n />\n </Stack>\n)\n\n/** What the Attributes and Interactions tabs say about a layout element. */\nconst LayoutElementNote = ({\n selection,\n}: {\n selection: LayoutElementSelection\n}) => (\n <Stack spacing={1.5} sx={{ p: 2 }}>\n <Typography variant=\"body2\" color=\"text.secondary\">\n {`This element belongs to the shared layout${\n selection.layoutName ? ` \"${selection.layoutName}\"` : ''\n }. Its content is edited in the layout itself — use Edit layout above ` +\n 'the canvas. On this page you can change how it looks on the Styles tab.'}\n </Typography>\n <Button\n size=\"small\"\n variant=\"outlined\"\n onClick={() => layoutStyleSelection.clear()}\n >\n {'Back to page elements'}\n </Button>\n </Stack>\n)\n\nfunction withLastSelectedNode<P>(\n WrappedComponent: JSX.ComponentType<P & { node: Besigner.LastSelectedNode }>,\n /**\n * What this tab shows while a layout element is the target (AGL-3286):\n * `styles` hands the wrapped Styles form the screen root and the target;\n * `note` says where the element's content is edited.\n */\n layoutMode: 'styles' | 'note' = 'note',\n) {\n const displayName = getDisplayName(WrappedComponent)\n\n const WithLastSelectedNode = observer((props: P) => {\n const { ...rest } = props\n const layoutTarget = layoutStyleSelection.current\n const selected = Besigner.focus.getLastSelected()\n /**\n * The LIVE node for that selection, re-resolved by id every render\n * (AGL-2486).\n *\n * The focus store holds node OBJECTS, not ids. Anything that replaces the\n * canvas map wholesale — `undo`, `redo`, a co-editing `applyNodes`, a\n * local-draft restore — builds fresh node instances and leaves the store\n * pointing at the pre-restore ones. The panels then read their fields from\n * an orphan and, worse, write back through it: `updateNodeProps` assigns\n * `node.props` on an object the canvas no longer owns, so the edit lands\n * nowhere. Nothing throws and nothing marks the document dirty, so an\n * author sees their new text in the box, an unchanged canvas, and `UP TO\n * DATE` — the reported \"the Text attribute silently discards edits\".\n *\n * Resolving here rather than in the three panels because they share this\n * one seam, and it is `observer`-tracked: `getNode` reads the observable\n * map, so a restore re-renders the panel with the live node instead of\n * leaving stale values in the fields.\n *\n * A node the map no longer has (deleted, or a test node that was never in\n * it) falls back to the stored object, which is exactly today's behaviour\n * for that case — there is no live node to prefer.\n */\n const lastSelected = selected\n ? canvas.getNode(selected.$id) ?? selected\n : selected\n\n if (layoutTarget) {\n // The page's layout overrides are kept on the screen root, so that is\n // the node the Styles form is handed; the target says which slice.\n const root = canvas.getNode(NODE_ROOT_ID)\n return (\n <>\n <LayoutElementHeader selection={layoutTarget} />\n {layoutMode === 'styles' && root ? (\n <WrappedComponent\n node={root}\n {...({ layoutTarget } as any)}\n {...rest}\n />\n ) : (\n <LayoutElementNote selection={layoutTarget} />\n )}\n </>\n )\n }\n\n return (\n <>\n {!lastSelected ? (\n emptyView\n ) : (\n <>\n {/* One header for all three right-panel tabs, so Attributes,\n Styles and Info cannot disagree about what is selected. */}\n <SelectedNodeHeader node={lastSelected} />\n <WrappedComponent node={lastSelected} {...rest} />\n </>\n )}\n </>\n )\n })\n WithLastSelectedNode.displayName = `WithLastSelectedNode(${displayName})`\n hoistNonReactStatics(WithLastSelectedNode, WrappedComponent)\n\n return WithLastSelectedNode\n}\n\nconst withTabPanelInner = (Component: ComponentType<any>) => (props: any) => {\n return (\n <TabPanelInner sx={{ p: 2 }}>\n <Component {...props} />\n </TabPanelInner>\n )\n}\n\n/**\n * The Attributes form with the host app's section beneath it (AGL-2940):\n * whatever `BesignerInspectorExtrasContext` carries, drawn under the\n * selected element's own fields — for that element, when the host supplied\n * a function — and nothing when the host supplied nothing.\n *\n * The selection travels with `editable` (AGL-2908), the same rule the form's\n * own Save as reusable component and Detach actions are drawn under: the\n * canvas root and locked layout chrome answer false. It is read here because\n * a host section has the node and not the editor, and the rule is the drag\n * manager's.\n */\nconst ElementPropsFormWithExtras = (props: any) => {\n const supplied = useBesignerInspectorExtras()\n const inspected = besignerInspected(props.node)\n const extras = inspected ? inspectorExtrasFor(supplied, inspected) : null\n return (\n <>\n <ElementPropsForm {...props} />\n {extras ? <Box sx={{ pt: 2 }}>{extras}</Box> : null}\n </>\n )\n}\n\nconst ElementsTree = forwardRef<any, NodeTreeViewProps>((props, ref) => {\n const handleAddElementClick = useAddElementDrawerCallback()\n return (\n <TabPanelInner sx={{ pl: 0.5 }}>\n <Box\n sx={{\n px: 0.05,\n pb: 1,\n pt: 1,\n display: 'flex',\n alignItems: 'center',\n }}\n >\n <Button\n color=\"primary\"\n startIcon={\n <MdiIcon fontSize=\"inherit\" path={ICON_VARIANT_MODIFY_ADD.path} />\n }\n onClick={() =>\n handleAddElementClick(Besigner.focus.getLastSelected())\n }\n >\n {'Add Element'}\n </Button>\n {/* The hierarchy is the one panel whose rules are not visible in it\n (AGL-2167): which elements accept children, and what dropping on\n an edge does versus dropping in the center. */}\n <HelpTip\n title=\"Drag, drop & hierarchy\"\n excerpt=\"Reparent by dragging here or on the canvas. Containers accept children; dropping on a leaf element makes a sibling instead.\"\n href={besignerDocsUrl('dragDropHierarchy', '#drop-zones-edges-vs-center')}\n sx={{ ml: 'auto', mr: 0.5, fontSize: '0.9em' }}\n />\n </Box>\n <NodeTreeView ref={ref} {...props} />\n </TabPanelInner>\n )\n})\n\nconst panelTabs: Partial<Record<BesignerPanelKey, any>> = {\n panelLeft: {\n defaultTab: BesignerPanelTabFlag.ELEMENTS_TREE,\n panel: {\n id: 'left',\n anchor: 'left',\n 'aria-label': 'left toolbox panel',\n },\n tabs: [\n {\n value: BesignerPanelTabFlag.ELEMENTS_TREE,\n tab: {\n icon: { path: ICON_VARIANT_ELEMENT_TREE_VIEW.path },\n label: 'Hierarchy',\n },\n panel: {\n Component: ElementsTree,\n },\n },\n {\n value: BesignerPanelTabFlag.ELEMENT_BROWSE,\n tab: {\n icon: { path: ICON_VARIANT_ELEMENT_BROWSE.path },\n label: 'Elements',\n },\n panel: {\n Component: ComponentAccordionList,\n },\n },\n ],\n },\n panelRight: {\n // Attributes first and open by default — it is what you reach for on\n // selecting an element. Tab order here is display order only; the flag\n // values are persisted in panel state, so they stay put.\n defaultTab: BesignerPanelTabFlag.ELEMENT_PROPS_FORM,\n panel: {\n id: 'right',\n anchor: 'right',\n 'aria-label': 'right toolbox panel',\n },\n tabs: [\n {\n value: BesignerPanelTabFlag.ELEMENT_PROPS_FORM,\n tab: {\n icon: { path: ICON_VARIANT_ELEMENT_PROPERTIES.path },\n label: 'Attributes',\n },\n panel: {\n Component: withLastSelectedNode(withTabPanelInner(ElementPropsFormWithExtras)),\n },\n },\n {\n value: BesignerPanelTabFlag.ELEMENT_STYLES,\n tab: {\n icon: { path: ICON_VARIANT_ELEMENT_STYLES.path },\n label: 'Styles',\n },\n panel: {\n Component: withLastSelectedNode(ElementStylesForm as any, 'styles'),\n },\n },\n /*\n * Interactions, between Styles and where Info used to be.\n *\n * They lived at the bottom of Attributes, under every field the\n * component declares — below the fold on anything with more than a\n * handful, so an author had no reason to believe the element had any.\n * An interaction is not an attribute: it is a behaviour, authored in a\n * dialog rather than a field, and it belongs beside the styles as a\n * peer.\n *\n * INFO IS GONE. Its two accordions are reference detail about the\n * component and the node's ids — worth having, not worth a tab — and\n * they now sit at the bottom of Attributes, beside the fields they\n * describe. Its flag value stays reserved; panel state is persisted,\n * and a reader whose last session ended on Info would otherwise return\n * to a tab id that means something else.\n */\n {\n value: BesignerPanelTabFlag.ELEMENT_INTERACTIONS,\n tab: {\n icon: { path: ICON_VARIANT_ELEMENT_INTERACTIONS.path },\n label: 'Interactions',\n },\n panel: {\n Component: withLastSelectedNode(\n withTabPanelInner(ElementInteractionsForm as any),\n ),\n },\n },\n ],\n },\n}\n\nexport interface AsidePanelComponentProps extends WorkspacePanelComponentProps {\n panel: BesignerPanelKey\n}\n\nexport const AsidePanelComponent = forwardRef<any, AsidePanelComponentProps>(\n (props, ref) => {\n const { children, panel: panelKey, ...rest } = props\n\n // Republish the page's site theme for surfaces that render OUTSIDE the\n // page tree (AGL-2486). This panel is inside `HostThemeDocumentContext`;\n // the Choose-element dialog — rendered by `withBesignerContext`, which\n // wraps the page — is not, and its element preview was painting the\n // console's brand onto someone else's site.\n usePublishActiveHostTheme()\n\n const [panel, setPanel] = useAglynBesignerPanel(panelKey)\n const {\n panel: { id, ...panelProps },\n defaultTab,\n tabs,\n } = panelTabs[panelKey]\n const { toggled, tab, size } = panel || {}\n const value = tab || defaultTab\n\n // The bottom-right corner belongs to this panel while it is open\n // (AGL-2486), so publish how far a viewport-fixed affordance has to\n // stand off to clear it. A console-dock launcher reads this; the console's\n // own chrome leaves the corner free and never sets it, which is why the\n // variable carries the offset rather than the panel width — an unset\n // variable then means \"the corner is yours\" everywhere else.\n //\n // Kept in an effect on the LIVE panel state so it tracks the author\n // dragging the panel wider or collapsing it, and removed on unmount:\n // navigating from the besigner back into the console must not leave a\n // 395px inset behind on a page with no panel at all.\n // `size` is `string | number` on the panel state, so a numeric width is\n // parsed rather than added to: `'375' + 20` is `'37520'`, which is a\n // perfectly valid CSS length and would park the launcher off-screen.\n const panelWidth = Number.parseFloat(String(size ?? ''))\n const rightInset =\n panelKey === 'panelRight' && toggled && Number.isFinite(panelWidth)\n ? panelWidth + 20\n : null\n useEffect(() => {\n if (panelKey !== 'panelRight') return undefined\n const root = document.documentElement\n const property = '--aglyn-dock-inset-right'\n if (rightInset === null) {\n root.style.removeProperty(property)\n } else {\n root.style.setProperty(property, `${rightInset}px`)\n }\n return () => {\n root.style.removeProperty(property)\n }\n }, [panelKey, rightInset])\n\n const handleTabChange = useCallback(\n (e: SyntheticEvent, val: string) => {\n setPanel((panel) => ({ ...panel, tab: numberFromHexadecimal(val) }))\n },\n [setPanel],\n )\n\n return (\n <WorkspacePanelComponent\n ref={ref}\n id={`aglyn:panel-${id}`}\n aria-label=\"left toolbox panel\"\n size={size}\n open={toggled}\n component=\"aside\"\n {...panelProps}\n {...rest}\n >\n <MuiTabContext value={numberToHexadecimal(value)}>\n <Box sx={{ borderBottom: 1, borderColor: 'divider' }}>\n <MuiAppBar\n color=\"surface\"\n position=\"relative\"\n elevation={0}\n enableColorOnDark\n >\n <MuiTabList\n onChange={handleTabChange}\n variant=\"fullWidth\"\n sx={{\n '& .MuiTab-root': {\n '&.Mui-selected': {\n // Use sx string shorthands instead of palette callbacks so the\n // sx system resolves them via theme.vars (CSS custom-property refs)\n // rather than the static light-mode palette values.\n color: 'text.primary',\n backgroundColor: 'background.paper',\n },\n },\n '& .MuiTabs-indicator': {\n top: 0,\n backgroundColor: 'secondary.main',\n },\n }}\n >\n {tabs.map(({ value, tab: { icon, ...tab } }) => (\n <MuiTab\n key={value}\n // color={'tertiary'}\n value={numberToHexadecimal(value)}\n iconPosition=\"top\"\n icon={<MdiIcon {...icon} fontSize=\"small\" />}\n sx={{\n minHeight: 'unset',\n fontSize: (theme) => theme.typography.pxToRem(12),\n lineHeight: 0.8,\n pt: 1,\n }}\n {...tab}\n />\n ))}\n </MuiTabList>\n </MuiAppBar>\n </Box>\n\n {/* Site-theme color tokens (AGL-588): every COLOR_PICKER field\n in these panels — styles panel, attribute forms, email\n blocks — offers the site palette's token references. */}\n <SiteThemeColorTokensProvider>\n {tabs.map(({ value, panel: { Component, ...panel } }) => (\n <TabPanel\n key={value}\n value={numberToHexadecimal(value)}\n {...panel}\n >\n <Component />\n </TabPanel>\n ))}\n </SiteThemeColorTokensProvider>\n </MuiTabContext>\n\n {children}\n </WorkspacePanelComponent>\n )\n },\n)\n\nAsidePanelComponent.displayName = 'AsidePanelComponent'\nAsidePanelComponent.aglyn = true\n\nexport default AsidePanelComponent\n"],"names":["canvas","NODE_ROOT_ID","Besigner","BesignerPanelTabFlag","ICON_VARIANT_ELEMENT","ICON_VARIANT_ELEMENT_BROWSE","ICON_VARIANT_ELEMENT_INTERACTIONS","ICON_VARIANT_ELEMENT_PROPERTIES","ICON_VARIANT_ELEMENT_STYLES","ICON_VARIANT_ELEMENT_TREE_VIEW","ICON_VARIANT_MODIFY_ADD","HelpTip","MdiIcon","styled","getDisplayName","numberFromHexadecimal","numberToHexadecimal","hoistNonReactStatics","TabContext","MuiTabContext","TabList","MuiTabList","TabPanel","MuiTabPanel","AppBar","MuiAppBar","Box","Button","Chip","Stack","Tab","MuiTab","Typography","observer","forwardRef","useCallback","useEffect","useAddElementDrawerCallback","useAglynBesignerPanel","ElementInteractionsForm","ComponentAccordionList","ElementPropsForm","ElementStylesForm","NodeTreeView","SiteThemeColorTokensProvider","usePublishActiveHostTheme","besignerInspected","layoutStyleSelection","inspectorExtrasFor","useBesignerInspectorExtras","besignerDocsUrl","WorkspacePanelComponent","name","padding","overflow","height","TabPanelInner","theme","width","emptyView","direction","component","sx","justifyContent","p","color","variant","align","opacity","fontSize","path","div","SelectedNodeHeader","node","labelShort","componentSchema","displayName","subtitle","toLowerCase","spacing","alignItems","px","py","borderBottom","borderColor","noWrap","flex","minWidth","size","label","LayoutElementHeader","selection","LayoutElementNote","layoutName","onClick","clear","withLastSelectedNode","WrappedComponent","layoutMode","WithLastSelectedNode","props","rest","layoutTarget","current","selected","focus","getLastSelected","lastSelected","getNode","$id","root","withTabPanelInner","Component","ElementPropsFormWithExtras","supplied","inspected","extras","pt","ElementsTree","ref","handleAddElementClick","pl","pb","display","startIcon","title","excerpt","href","ml","mr","panelTabs","panelLeft","defaultTab","ELEMENTS_TREE","panel","id","anchor","tabs","value","tab","icon","ELEMENT_BROWSE","panelRight","ELEMENT_PROPS_FORM","ELEMENT_STYLES","ELEMENT_INTERACTIONS","AsidePanelComponent","children","panelKey","setPanel","panelProps","toggled","panelWidth","Number","parseFloat","String","rightInset","isFinite","undefined","document","documentElement","property","style","removeProperty","setProperty","handleTabChange","e","val","aria-label","open","position","elevation","enableColorOnDark","onChange","backgroundColor","top","map","iconPosition","minHeight","typography","pxToRem","lineHeight","aglyn"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../../../../libs/besigner/feature/designer/src/lib/components/aside-panel.component.tsx"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { canvas, NODE_ROOT_ID } from '@aglyn/aglyn'\nimport * as Besigner from '@aglyn/besigner'\nimport {\n type BesignerPanelKey,\n BesignerPanelTabFlag,\n} from '@aglyn/besigner'\nimport {\n ICON_VARIANT_ELEMENT,\n ICON_VARIANT_ELEMENT_BROWSE,\n ICON_VARIANT_ELEMENT_INTERACTIONS,\n ICON_VARIANT_ELEMENT_PROPERTIES,\n ICON_VARIANT_ELEMENT_STYLES,\n ICON_VARIANT_ELEMENT_TREE_VIEW,\n ICON_VARIANT_MODIFY_ADD,\n} from '@aglyn/shared-data-enums'\nimport { HelpTip, MdiIcon } from '@aglyn/shared-ui-jsx'\nimport { mergeSxProps, styled } from '@aglyn/shared-ui-theme'\nimport {\n getDisplayName,\n numberFromHexadecimal,\n numberToHexadecimal,\n} from '@aglyn/shared-util-tools'\nimport { hoistNonReactStatics } from '@aglyn/shared-util-vendor'\nimport {\n TabContext as MuiTabContext,\n TabList as MuiTabList,\n TabPanel as MuiTabPanel,\n type TabPanelProps as MuiTabPanelProps,\n} from '@mui/lab'\nimport {\n AppBar as MuiAppBar,\n Box,\n Button,\n Chip,\n Stack,\n Tab as MuiTab,\n Typography,\n useMediaQuery,\n useTheme,\n} from '@mui/material'\nimport { observer } from 'mobx-react-lite'\nimport {\n type ComponentType,\n forwardRef,\n type SyntheticEvent,\n useCallback,\n useEffect,\n useMemo,\n useState,\n} from 'react'\nimport useAddElementDrawerCallback from '../hooks/use-add-element-drawer-callback'\nimport useAglynBesignerPanel from '../hooks/use-aglyn-besigner-panel'\nimport AccordionListComponent from './accordion-list.component'\nimport ElementInteractionsForm from './element-interactions-form.component'\nimport ComponentAccordionList from './component-accordion-list'\nimport ElementPropsForm from './element-props-form.component'\nimport ElementStylesForm from './element-styles-form.component'\nimport NodeTreeView, { type NodeTreeViewProps } from './node-tree-view'\nimport SiteThemeColorTokensProvider from './site-theme-color-tokens-provider.component'\nimport { usePublishActiveHostTheme } from '../utils/active-host-theme'\nimport { besignerInspected } from '../contexts/inspected-selection'\nimport {\n type LayoutElementSelection,\n layoutStyleSelection,\n} from '../contexts/layout-style-selection'\nimport {\n inspectorExtrasFor,\n useBesignerInspectorExtras,\n} from '../contexts/inspector-extras-context'\nimport { besignerDocsUrl } from '../utils/docs-help'\nimport WorkspacePanelComponent, {\n type WorkspacePanelComponentProps,\n} from './workspace-panel.component'\n\nconst TabPanel = styled(MuiTabPanel, {\n name: 'AglynTabPanel',\n})<MuiTabPanelProps>({\n padding: 0,\n overflow: 'auto',\n height: '100%',\n})\nconst TabPanelInner = styled('div', {\n name: 'AglynTabPanelInner',\n})(({ theme }) => ({\n width: '100%',\n}))\n\nconst emptyView = (\n <Stack\n direction=\"column\"\n component={TabPanelInner}\n sx={{\n justifyContent: 'center',\n height: 1,\n p: 2,\n }}\n >\n <Typography\n color=\"textSecondary\"\n variant=\"overline\"\n component=\"div\"\n align=\"center\"\n >\n <MdiIcon\n sx={{ opacity: 0.3, fontSize: 80 }}\n path={ICON_VARIANT_ELEMENT.path}\n />\n <div>{'Select an element'}</div>\n </Typography>\n </Stack>\n)\n\n\n/**\n * `Hero · Section` with a `SELECTED` tag — the inspector header the\n * `/product` hero mockup shows (AGL-2175).\n *\n * The right panel had no header at all: three tabs of controls with\n * nothing naming what they act on. On a canvas where clicking a child\n * moves the selection under you, that is the difference between editing\n * the section and editing the heading inside it — and the panel looked\n * identical either way.\n *\n * The second half is the COMPONENT, not a category: `labelShort` is the\n * preset's name (`Hero`) and the schema's is what it actually is\n * (`Section`). They are the same word often enough that it is dropped\n * when it would only repeat itself.\n */\nconst SelectedNodeHeader = observer(\n ({ node }: { node: Besigner.LastSelectedNode }) => {\n const name = node?.labelShort ?? ''\n const component = (node as { componentSchema?: { displayName?: string } })\n ?.componentSchema?.displayName\n const subtitle =\n component && component.toLowerCase() !== name.toLowerCase()\n ? `${name} · ${component}`\n : name\n return (\n <Stack\n direction=\"row\"\n spacing={1}\n sx={{\n alignItems: 'center',\n px: 2,\n py: 1,\n borderBottom: 1,\n borderColor: 'divider',\n }}\n >\n <Typography variant=\"subtitle2\" noWrap sx={{ flex: 1, minWidth: 0 }}>\n {subtitle || 'Element'}\n </Typography>\n <Chip\n size=\"small\"\n variant=\"outlined\"\n color=\"secondary\"\n label=\"SELECTED\"\n sx={{ height: 18, '& .MuiChip-label': { px: 0.75, fontSize: 10 } }}\n />\n </Stack>\n )\n },\n)\nSelectedNodeHeader.displayName = 'SelectedNodeHeader'\n\n/**\n * The panel while a shared-layout element is the target (AGL-3286): named in\n * the header like any selection, and marked as the layout's, styles only.\n */\nconst LayoutElementHeader = ({\n selection,\n}: {\n selection: LayoutElementSelection\n}) => (\n <Stack\n direction=\"row\"\n spacing={1}\n sx={{\n alignItems: 'center',\n px: 2,\n py: 1,\n borderBottom: 1,\n borderColor: 'divider',\n }}\n >\n <Typography variant=\"subtitle2\" noWrap sx={{ flex: 1, minWidth: 0 }}>\n {`${selection.label} · Layout`}\n </Typography>\n <Chip\n size=\"small\"\n variant=\"outlined\"\n color=\"info\"\n label=\"STYLES ONLY\"\n sx={{ height: 18, '& .MuiChip-label': { px: 0.75, fontSize: 10 } }}\n />\n </Stack>\n)\n\n/** What the Attributes and Interactions tabs say about a layout element. */\nconst LayoutElementNote = ({\n selection,\n}: {\n selection: LayoutElementSelection\n}) => (\n <Stack spacing={1.5} sx={{ p: 2 }}>\n <Typography variant=\"body2\" color=\"text.secondary\">\n {`This element belongs to the shared layout${\n selection.layoutName ? ` \"${selection.layoutName}\"` : ''\n }. Its content is edited in the layout itself — use Edit layout above ` +\n 'the canvas. On this page you can change how it looks on the Styles tab.'}\n </Typography>\n <Button\n size=\"small\"\n variant=\"outlined\"\n onClick={() => layoutStyleSelection.clear()}\n >\n {'Back to page elements'}\n </Button>\n </Stack>\n)\n\nfunction withLastSelectedNode<P>(\n WrappedComponent: JSX.ComponentType<P & { node: Besigner.LastSelectedNode }>,\n /**\n * What this tab shows while a layout element is the target (AGL-3286):\n * `styles` hands the wrapped Styles form the screen root and the target;\n * `note` says where the element's content is edited.\n */\n layoutMode: 'styles' | 'note' = 'note',\n) {\n const displayName = getDisplayName(WrappedComponent)\n\n const WithLastSelectedNode = observer((props: P) => {\n const { ...rest } = props\n const layoutTarget = layoutStyleSelection.current\n const selected = Besigner.focus.getLastSelected()\n /**\n * The LIVE node for that selection, re-resolved by id every render\n * (AGL-2486).\n *\n * The focus store holds node OBJECTS, not ids. Anything that replaces the\n * canvas map wholesale — `undo`, `redo`, a co-editing `applyNodes`, a\n * local-draft restore — builds fresh node instances and leaves the store\n * pointing at the pre-restore ones. The panels then read their fields from\n * an orphan and, worse, write back through it: `updateNodeProps` assigns\n * `node.props` on an object the canvas no longer owns, so the edit lands\n * nowhere. Nothing throws and nothing marks the document dirty, so an\n * author sees their new text in the box, an unchanged canvas, and `UP TO\n * DATE` — the reported \"the Text attribute silently discards edits\".\n *\n * Resolving here rather than in the three panels because they share this\n * one seam, and it is `observer`-tracked: `getNode` reads the observable\n * map, so a restore re-renders the panel with the live node instead of\n * leaving stale values in the fields.\n *\n * A node the map no longer has (deleted, or a test node that was never in\n * it) falls back to the stored object, which is exactly today's behaviour\n * for that case — there is no live node to prefer.\n */\n const lastSelected = selected\n ? canvas.getNode(selected.$id) ?? selected\n : selected\n\n if (layoutTarget) {\n // The page's layout overrides are kept on the screen root, so that is\n // the node the Styles form is handed; the target says which slice.\n const root = canvas.getNode(NODE_ROOT_ID)\n return (\n <>\n <LayoutElementHeader selection={layoutTarget} />\n {layoutMode === 'styles' && root ? (\n <WrappedComponent\n node={root}\n {...({ layoutTarget } as any)}\n {...rest}\n />\n ) : (\n <LayoutElementNote selection={layoutTarget} />\n )}\n </>\n )\n }\n\n return (\n <>\n {!lastSelected ? (\n emptyView\n ) : (\n <>\n {/* One header for all three right-panel tabs, so Attributes,\n Styles and Info cannot disagree about what is selected. */}\n <SelectedNodeHeader node={lastSelected} />\n <WrappedComponent node={lastSelected} {...rest} />\n </>\n )}\n </>\n )\n })\n WithLastSelectedNode.displayName = `WithLastSelectedNode(${displayName})`\n hoistNonReactStatics(WithLastSelectedNode, WrappedComponent)\n\n return WithLastSelectedNode\n}\n\nconst withTabPanelInner = (Component: ComponentType<any>) => (props: any) => {\n return (\n <TabPanelInner sx={{ p: 2 }}>\n <Component {...props} />\n </TabPanelInner>\n )\n}\n\n/**\n * The Attributes form with the host app's section beneath it (AGL-2940):\n * whatever `BesignerInspectorExtrasContext` carries, drawn under the\n * selected element's own fields — for that element, when the host supplied\n * a function — and nothing when the host supplied nothing.\n *\n * The selection travels with `editable` (AGL-2908), the same rule the form's\n * own Save as reusable component and Detach actions are drawn under: the\n * canvas root and locked layout chrome answer false. It is read here because\n * a host section has the node and not the editor, and the rule is the drag\n * manager's.\n */\nconst ElementPropsFormWithExtras = (props: any) => {\n const supplied = useBesignerInspectorExtras()\n const inspected = besignerInspected(props.node)\n const extras = inspected ? inspectorExtrasFor(supplied, inspected) : null\n return (\n <>\n <ElementPropsForm {...props} />\n {extras ? <Box sx={{ pt: 2 }}>{extras}</Box> : null}\n </>\n )\n}\n\nconst ElementsTree = forwardRef<any, NodeTreeViewProps>((props, ref) => {\n const handleAddElementClick = useAddElementDrawerCallback()\n return (\n <TabPanelInner sx={{ pl: 0.5 }}>\n <Box\n sx={{\n px: 0.05,\n pb: 1,\n pt: 1,\n display: 'flex',\n alignItems: 'center',\n }}\n >\n <Button\n color=\"primary\"\n startIcon={\n <MdiIcon fontSize=\"inherit\" path={ICON_VARIANT_MODIFY_ADD.path} />\n }\n onClick={() =>\n handleAddElementClick(Besigner.focus.getLastSelected())\n }\n >\n {'Add Element'}\n </Button>\n {/* The hierarchy is the one panel whose rules are not visible in it\n (AGL-2167): which elements accept children, and what dropping on\n an edge does versus dropping in the center. */}\n <HelpTip\n title=\"Drag, drop & hierarchy\"\n excerpt=\"Reparent by dragging here or on the canvas. Containers accept children; dropping on a leaf element makes a sibling instead.\"\n href={besignerDocsUrl('dragDropHierarchy', '#drop-zones-edges-vs-center')}\n sx={{ ml: 'auto', mr: 0.5, fontSize: '0.9em' }}\n />\n </Box>\n <NodeTreeView ref={ref} {...props} />\n </TabPanelInner>\n )\n})\n\nconst panelTabs: Partial<Record<BesignerPanelKey, any>> = {\n panelLeft: {\n defaultTab: BesignerPanelTabFlag.ELEMENTS_TREE,\n panel: {\n id: 'left',\n anchor: 'left',\n 'aria-label': 'left toolbox panel',\n },\n tabs: [\n {\n value: BesignerPanelTabFlag.ELEMENTS_TREE,\n tab: {\n icon: { path: ICON_VARIANT_ELEMENT_TREE_VIEW.path },\n label: 'Hierarchy',\n },\n panel: {\n Component: ElementsTree,\n },\n },\n {\n value: BesignerPanelTabFlag.ELEMENT_BROWSE,\n tab: {\n icon: { path: ICON_VARIANT_ELEMENT_BROWSE.path },\n label: 'Elements',\n },\n panel: {\n Component: ComponentAccordionList,\n },\n },\n ],\n },\n panelRight: {\n // Attributes first and open by default — it is what you reach for on\n // selecting an element. Tab order here is display order only; the flag\n // values are persisted in panel state, so they stay put.\n defaultTab: BesignerPanelTabFlag.ELEMENT_PROPS_FORM,\n panel: {\n id: 'right',\n anchor: 'right',\n 'aria-label': 'right toolbox panel',\n },\n tabs: [\n {\n value: BesignerPanelTabFlag.ELEMENT_PROPS_FORM,\n tab: {\n icon: { path: ICON_VARIANT_ELEMENT_PROPERTIES.path },\n label: 'Attributes',\n },\n panel: {\n Component: withLastSelectedNode(withTabPanelInner(ElementPropsFormWithExtras)),\n },\n },\n {\n value: BesignerPanelTabFlag.ELEMENT_STYLES,\n tab: {\n icon: { path: ICON_VARIANT_ELEMENT_STYLES.path },\n label: 'Styles',\n },\n panel: {\n Component: withLastSelectedNode(ElementStylesForm as any, 'styles'),\n },\n },\n /*\n * Interactions, between Styles and where Info used to be.\n *\n * They lived at the bottom of Attributes, under every field the\n * component declares — below the fold on anything with more than a\n * handful, so an author had no reason to believe the element had any.\n * An interaction is not an attribute: it is a behaviour, authored in a\n * dialog rather than a field, and it belongs beside the styles as a\n * peer.\n *\n * INFO IS GONE. Its two accordions are reference detail about the\n * component and the node's ids — worth having, not worth a tab — and\n * they now sit at the bottom of Attributes, beside the fields they\n * describe. Its flag value stays reserved; panel state is persisted,\n * and a reader whose last session ended on Info would otherwise return\n * to a tab id that means something else.\n */\n {\n value: BesignerPanelTabFlag.ELEMENT_INTERACTIONS,\n tab: {\n icon: { path: ICON_VARIANT_ELEMENT_INTERACTIONS.path },\n label: 'Interactions',\n },\n panel: {\n Component: withLastSelectedNode(\n withTabPanelInner(ElementInteractionsForm as any),\n ),\n },\n },\n ],\n },\n}\n\nexport interface AsidePanelComponentProps extends WorkspacePanelComponentProps {\n panel: BesignerPanelKey\n}\n\nexport const AsidePanelComponent = forwardRef<any, AsidePanelComponentProps>(\n (props, ref) => {\n const { children, panel: panelKey, ...rest } = props\n\n // Republish the page's site theme for surfaces that render OUTSIDE the\n // page tree (AGL-2486). This panel is inside `HostThemeDocumentContext`;\n // the Choose-element dialog — rendered by `withBesignerContext`, which\n // wraps the page — is not, and its element preview was painting the\n // console's brand onto someone else's site.\n usePublishActiveHostTheme()\n\n const [panel, setPanel] = useAglynBesignerPanel(panelKey)\n const {\n panel: { id, ...panelProps },\n defaultTab,\n tabs,\n } = panelTabs[panelKey]\n const { toggled, tab, size } = panel || {}\n const value = tab || defaultTab\n\n // Below `md` there is no room for a docked panel beside the canvas, so\n // the panel overlays it as a temporary drawer instead (AGL-3599): from\n // its own side on a tablet, and as a bottom sheet on a phone, where a\n // side drawer would leave a sliver of canvas nobody can use.\n const theme = useTheme()\n const compact = useMediaQuery(theme.breakpoints.down('md'), {\n noSsr: true,\n })\n const phone = useMediaQuery(theme.breakpoints.down('sm'), { noSsr: true })\n const handleClose = useCallback(\n () => setPanel((prev) => ({ ...prev, toggled: false })),\n [setPanel],\n )\n const handleOpen = useCallback(\n () => setPanel((prev) => ({ ...prev, toggled: true })),\n [setPanel],\n )\n\n // The bottom-right corner belongs to this panel while it is open\n // (AGL-2486), so publish how far a viewport-fixed affordance has to\n // stand off to clear it. A console-dock launcher reads this; the console's\n // own chrome leaves the corner free and never sets it, which is why the\n // variable carries the offset rather than the panel width — an unset\n // variable then means \"the corner is yours\" everywhere else.\n //\n // Kept in an effect on the LIVE panel state so it tracks the author\n // dragging the panel wider or collapsing it, and removed on unmount:\n // navigating from the besigner back into the console must not leave a\n // 395px inset behind on a page with no panel at all.\n // `size` is `string | number` on the panel state, so a numeric width is\n // parsed rather than added to: `'375' + 20` is `'37520'`, which is a\n // perfectly valid CSS length and would park the launcher off-screen.\n const panelWidth = Number.parseFloat(String(size ?? ''))\n // An overlaying drawer owns no corner: it is dismissed before anything\n // under it is reached.\n const rightInset =\n panelKey === 'panelRight' &&\n toggled &&\n !compact &&\n Number.isFinite(panelWidth)\n ? panelWidth + 20\n : null\n useEffect(() => {\n if (panelKey !== 'panelRight') return undefined\n const root = document.documentElement\n const property = '--aglyn-dock-inset-right'\n if (rightInset === null) {\n root.style.removeProperty(property)\n } else {\n root.style.setProperty(property, `${rightInset}px`)\n }\n return () => {\n root.style.removeProperty(property)\n }\n }, [panelKey, rightInset])\n\n const handleTabChange = useCallback(\n (e: SyntheticEvent, val: string) => {\n setPanel((panel) => ({ ...panel, tab: numberFromHexadecimal(val) }))\n },\n [setPanel],\n )\n\n return (\n <WorkspacePanelComponent\n ref={ref}\n id={`aglyn:panel-${id}`}\n aria-label=\"left toolbox panel\"\n size={size}\n open={toggled}\n component=\"aside\"\n temporary={compact}\n temporaryAnchor={phone ? 'bottom' : undefined}\n onClose={handleClose}\n onOpen={handleOpen}\n {...panelProps}\n {...rest}\n >\n <MuiTabContext value={numberToHexadecimal(value)}>\n <Box sx={{ borderBottom: 1, borderColor: 'divider' }}>\n <MuiAppBar\n color=\"surface\"\n position=\"relative\"\n elevation={0}\n enableColorOnDark\n >\n <MuiTabList\n onChange={handleTabChange}\n variant=\"fullWidth\"\n sx={{\n '& .MuiTab-root': {\n '&.Mui-selected': {\n // Use sx string shorthands instead of palette callbacks so the\n // sx system resolves them via theme.vars (CSS custom-property refs)\n // rather than the static light-mode palette values.\n color: 'text.primary',\n backgroundColor: 'background.paper',\n },\n },\n '& .MuiTabs-indicator': {\n top: 0,\n backgroundColor: 'secondary.main',\n },\n }}\n >\n {tabs.map(({ value, tab: { icon, ...tab } }) => (\n <MuiTab\n key={value}\n // color={'tertiary'}\n value={numberToHexadecimal(value)}\n iconPosition=\"top\"\n icon={<MdiIcon {...icon} fontSize=\"small\" />}\n sx={{\n minHeight: 'unset',\n fontSize: (theme) => theme.typography.pxToRem(12),\n lineHeight: 0.8,\n pt: 1,\n }}\n {...tab}\n />\n ))}\n </MuiTabList>\n </MuiAppBar>\n </Box>\n\n {/* Site-theme color tokens (AGL-588): every COLOR_PICKER field\n in these panels — styles panel, attribute forms, email\n blocks — offers the site palette's token references. */}\n <SiteThemeColorTokensProvider>\n {tabs.map(({ value, panel: { Component, ...panel } }) => (\n <TabPanel\n key={value}\n value={numberToHexadecimal(value)}\n {...panel}\n >\n <Component />\n </TabPanel>\n ))}\n </SiteThemeColorTokensProvider>\n </MuiTabContext>\n\n {children}\n </WorkspacePanelComponent>\n )\n },\n)\n\nAsidePanelComponent.displayName = 'AsidePanelComponent'\nAsidePanelComponent.aglyn = true\n\nexport default AsidePanelComponent\n"],"names":["canvas","NODE_ROOT_ID","Besigner","BesignerPanelTabFlag","ICON_VARIANT_ELEMENT","ICON_VARIANT_ELEMENT_BROWSE","ICON_VARIANT_ELEMENT_INTERACTIONS","ICON_VARIANT_ELEMENT_PROPERTIES","ICON_VARIANT_ELEMENT_STYLES","ICON_VARIANT_ELEMENT_TREE_VIEW","ICON_VARIANT_MODIFY_ADD","HelpTip","MdiIcon","styled","getDisplayName","numberFromHexadecimal","numberToHexadecimal","hoistNonReactStatics","TabContext","MuiTabContext","TabList","MuiTabList","TabPanel","MuiTabPanel","AppBar","MuiAppBar","Box","Button","Chip","Stack","Tab","MuiTab","Typography","useMediaQuery","useTheme","observer","forwardRef","useCallback","useEffect","useAddElementDrawerCallback","useAglynBesignerPanel","ElementInteractionsForm","ComponentAccordionList","ElementPropsForm","ElementStylesForm","NodeTreeView","SiteThemeColorTokensProvider","usePublishActiveHostTheme","besignerInspected","layoutStyleSelection","inspectorExtrasFor","useBesignerInspectorExtras","besignerDocsUrl","WorkspacePanelComponent","name","padding","overflow","height","TabPanelInner","theme","width","emptyView","direction","component","sx","justifyContent","p","color","variant","align","opacity","fontSize","path","div","SelectedNodeHeader","node","labelShort","componentSchema","displayName","subtitle","toLowerCase","spacing","alignItems","px","py","borderBottom","borderColor","noWrap","flex","minWidth","size","label","LayoutElementHeader","selection","LayoutElementNote","layoutName","onClick","clear","withLastSelectedNode","WrappedComponent","layoutMode","WithLastSelectedNode","props","rest","layoutTarget","current","selected","focus","getLastSelected","lastSelected","getNode","$id","root","withTabPanelInner","Component","ElementPropsFormWithExtras","supplied","inspected","extras","pt","ElementsTree","ref","handleAddElementClick","pl","pb","display","startIcon","title","excerpt","href","ml","mr","panelTabs","panelLeft","defaultTab","ELEMENTS_TREE","panel","id","anchor","tabs","value","tab","icon","ELEMENT_BROWSE","panelRight","ELEMENT_PROPS_FORM","ELEMENT_STYLES","ELEMENT_INTERACTIONS","AsidePanelComponent","children","panelKey","setPanel","panelProps","toggled","compact","breakpoints","down","noSsr","phone","handleClose","prev","handleOpen","panelWidth","Number","parseFloat","String","rightInset","isFinite","undefined","document","documentElement","property","style","removeProperty","setProperty","handleTabChange","e","val","aria-label","open","temporary","temporaryAnchor","onClose","onOpen","position","elevation","enableColorOnDark","onChange","backgroundColor","top","map","iconPosition","minHeight","typography","pxToRem","lineHeight","aglyn"],"mappings":"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"}
@@ -16,7 +16,7 @@
16
16
  */ import { _ as _extends } from "@swc/helpers/_/_extends";
17
17
  import { _ as _object_without_properties_loose } from "@swc/helpers/_/_object_without_properties_loose";
18
18
  import { jsx as _jsx } from "react/jsx-runtime";
19
- import { DndContext, KeyboardSensor, MeasuringStrategy, MouseSensor, PointerSensor, pointerWithin, TouchSensor, useSensor, useSensors } from "@dnd-kit/core";
19
+ import { DndContext, KeyboardSensor, MeasuringStrategy, PointerSensor, pointerWithin, TouchSensor, useSensor, useSensors } from "@dnd-kit/core";
20
20
  import { getEventCoordinates } from "@dnd-kit/utilities";
21
21
  import { DndProvider } from "react-dnd";
22
22
  import { HTML5Backend } from "react-dnd-html5-backend";
@@ -33,6 +33,31 @@ export const snapDraggingToCursor = ({ activatorEvent, draggingNodeRect, transfo
33
33
  }
34
34
  return transform;
35
35
  };
36
+ /**
37
+ * Pointer events cover mouse, pen AND touch, and dnd-kit hands a gesture to
38
+ * whichever sensor's activator claims it first — `pointerdown` always fires
39
+ * before `touchstart`, so a plain PointerSensor would swallow every touch and
40
+ * the TouchSensor's press-and-hold would never run. Declining touch pointers
41
+ * here leaves them to the TouchSensor, which is what lets a finger scroll the
42
+ * palette, the layers tree and the canvas without picking anything up.
43
+ */ let NonTouchPointerSensor = class NonTouchPointerSensor extends PointerSensor {
44
+ };
45
+ NonTouchPointerSensor.activators = PointerSensor.activators.map((activator)=>_extends({}, activator, {
46
+ handler: (event, options)=>event.nativeEvent.pointerType !== 'touch' && activator.handler(event, options)
47
+ }));
48
+ /**
49
+ * A mouse or pen drag starts after a few pixels of travel, so a click on a
50
+ * drag handle (the overlay's move button, a palette card) stays a click.
51
+ */ const POINTER_ACTIVATION = {
52
+ distance: 6
53
+ };
54
+ /**
55
+ * A finger drag starts after a short hold; moving further than the tolerance
56
+ * before then is a scroll, and the drag never starts.
57
+ */ const TOUCH_ACTIVATION = {
58
+ delay: 250,
59
+ tolerance: 8
60
+ };
36
61
  export function BesignerDndContext(props) {
37
62
  const { children, options } = props, rest = _object_without_properties_loose(props, [
38
63
  "children",
@@ -47,7 +72,11 @@ export function BesignerDndContext(props) {
47
72
  delayMouseStart: 0,
48
73
  touchSlop: 0
49
74
  }, options);
50
- const sensors = useSensors(useSensor(MouseSensor), useSensor(PointerSensor), useSensor(TouchSensor), useSensor(KeyboardSensor));
75
+ const sensors = useSensors(useSensor(NonTouchPointerSensor, {
76
+ activationConstraint: POINTER_ACTIVATION
77
+ }), useSensor(TouchSensor, {
78
+ activationConstraint: TOUCH_ACTIVATION
79
+ }), useSensor(KeyboardSensor));
51
80
  return /*#__PURE__*/ _jsx(DndProvider, _extends({
52
81
  backend: HTML5Backend,
53
82
  options: opts
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../../libs/besigner/feature/designer/src/lib/components/besigner-dnd-context.component.tsx"],"sourcesContent":["/**\n * @license\n * Copyright 2023 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { Modifier } from '@dnd-kit/core'\nimport {\n DndContext,\n KeyboardSensor,\n MeasuringStrategy,\n MouseSensor,\n PointerSensor,\n pointerWithin,\n TouchSensor,\n useSensor,\n useSensors,\n} from '@dnd-kit/core'\nimport { getEventCoordinates } from '@dnd-kit/utilities'\nimport type { BackendFactory } from 'dnd-core'\nimport { DndProvider } from 'react-dnd'\nimport { HTML5Backend } from 'react-dnd-html5-backend'\n\nexport const snapDraggingToCursor: Modifier = ({\n activatorEvent,\n draggingNodeRect,\n transform,\n}) => {\n if (draggingNodeRect && activatorEvent) {\n const activatorCoordinates = getEventCoordinates(activatorEvent)\n if (!activatorCoordinates) return transform\n\n const offsetX = activatorCoordinates.x - draggingNodeRect.left\n const offsetY = activatorCoordinates.y - draggingNodeRect.top\n\n return {\n ...transform,\n x: transform.x + offsetX + 2,\n y: transform.y + offsetY + 2,\n }\n }\n\n return transform\n}\nexport interface BesignerDndContextProps<BackendContext, BackendOptions> {\n children?: JSX.Children\n backend?: BackendFactory\n context?: BackendContext\n options?: BackendOptions\n debugMode?: boolean\n}\n\nexport function BesignerDndContext<T, U>(props: BesignerDndContextProps<T, U>) {\n const { children, options, ...rest } = props\n const opts = {\n enableTouchEvents: true,\n enableMouseEvents: true,\n enableKeyboardEvents: true,\n delay: 0,\n delayTouchStart: 0,\n delayMouseStart: 0,\n touchSlop: 0,\n ...options,\n }\n\n const sensors = useSensors(\n useSensor(MouseSensor),\n useSensor(PointerSensor),\n useSensor(TouchSensor),\n useSensor(KeyboardSensor),\n )\n\n return (\n <DndProvider backend={HTML5Backend} options={opts} {...rest} debugMode>\n <DndContext\n sensors={sensors}\n modifiers={[snapDraggingToCursor]}\n collisionDetection={pointerWithin}\n measuring={{\n droppable: {\n strategy: MeasuringStrategy.Always,\n },\n }}\n >\n {children}\n </DndContext>\n </DndProvider>\n )\n}\nBesignerDndContext.displayName = 'BesignerDndContext'\nBesignerDndContext.aglyn = true\n\nexport default BesignerDndContext\n"],"names":["DndContext","KeyboardSensor","MeasuringStrategy","MouseSensor","PointerSensor","pointerWithin","TouchSensor","useSensor","useSensors","getEventCoordinates","DndProvider","HTML5Backend","snapDraggingToCursor","activatorEvent","draggingNodeRect","transform","activatorCoordinates","offsetX","x","left","offsetY","y","top","BesignerDndContext","props","children","options","rest","opts","enableTouchEvents","enableMouseEvents","enableKeyboardEvents","delay","delayTouchStart","delayMouseStart","touchSlop","sensors","backend","debugMode","modifiers","collisionDetection","measuring","droppable","strategy","Always","displayName","aglyn"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC;;;AAGD,SACEA,UAAU,EACVC,cAAc,EACdC,iBAAiB,EACjBC,WAAW,EACXC,aAAa,EACbC,aAAa,EACbC,WAAW,EACXC,SAAS,EACTC,UAAU,QACL,gBAAe;AACtB,SAASC,mBAAmB,QAAQ,qBAAoB;AAExD,SAASC,WAAW,QAAQ,YAAW;AACvC,SAASC,YAAY,QAAQ,0BAAyB;AAEtD,OAAO,MAAMC,uBAAiC,CAAC,EAC7CC,cAAc,EACdC,gBAAgB,EAChBC,SAAS,EACV;IACC,IAAID,oBAAoBD,gBAAgB;QACtC,MAAMG,uBAAuBP,oBAAoBI;QACjD,IAAI,CAACG,sBAAsB,OAAOD;QAElC,MAAME,UAAUD,qBAAqBE,CAAC,GAAGJ,iBAAiBK,IAAI;QAC9D,MAAMC,UAAUJ,qBAAqBK,CAAC,GAAGP,iBAAiBQ,GAAG;QAE7D,OAAO,aACFP;YACHG,GAAGH,UAAUG,CAAC,GAAGD,UAAU;YAC3BI,GAAGN,UAAUM,CAAC,GAAGD,UAAU;;IAE/B;IAEA,OAAOL;AACT,EAAC;AASD,OAAO,SAASQ,mBAAyBC,KAAoC;IAC3E,MAAM,EAAEC,QAAQ,EAAEC,OAAO,EAAW,GAAGF,OAATG,wCAASH;;;;IACvC,MAAMI,OAAO;QACXC,mBAAmB;QACnBC,mBAAmB;QACnBC,sBAAsB;QACtBC,OAAO;QACPC,iBAAiB;QACjBC,iBAAiB;QACjBC,WAAW;OACRT;IAGL,MAAMU,UAAU5B,WACdD,UAAUJ,cACVI,UAAUH,gBACVG,UAAUD,cACVC,UAAUN;IAGZ,qBACE,KAACS;QAAY2B,SAAS1B;QAAce,SAASE;OAAUD;QAAMW,SAAS;kBACpE,cAAA,KAACtC;YACCoC,SAASA;YACTG,WAAW;gBAAC3B;aAAqB;YACjC4B,oBAAoBnC;YACpBoC,WAAW;gBACTC,WAAW;oBACTC,UAAUzC,kBAAkB0C,MAAM;gBACpC;YACF;sBAECnB;;;AAIT;AACAF,mBAAmBsB,WAAW,GAAG;AACjCtB,mBAAmBuB,KAAK,GAAG;AAE3B,eAAevB,mBAAkB"}
1
+ {"version":3,"sources":["../../../../../../../../libs/besigner/feature/designer/src/lib/components/besigner-dnd-context.component.tsx"],"sourcesContent":["/**\n * @license\n * Copyright 2023 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { Modifier } from '@dnd-kit/core'\nimport {\n DndContext,\n KeyboardSensor,\n MeasuringStrategy,\n PointerSensor,\n pointerWithin,\n TouchSensor,\n useSensor,\n useSensors,\n} from '@dnd-kit/core'\nimport { getEventCoordinates } from '@dnd-kit/utilities'\nimport type { BackendFactory } from 'dnd-core'\nimport { DndProvider } from 'react-dnd'\nimport { HTML5Backend } from 'react-dnd-html5-backend'\n\nexport const snapDraggingToCursor: Modifier = ({\n activatorEvent,\n draggingNodeRect,\n transform,\n}) => {\n if (draggingNodeRect && activatorEvent) {\n const activatorCoordinates = getEventCoordinates(activatorEvent)\n if (!activatorCoordinates) return transform\n\n const offsetX = activatorCoordinates.x - draggingNodeRect.left\n const offsetY = activatorCoordinates.y - draggingNodeRect.top\n\n return {\n ...transform,\n x: transform.x + offsetX + 2,\n y: transform.y + offsetY + 2,\n }\n }\n\n return transform\n}\n/**\n * Pointer events cover mouse, pen AND touch, and dnd-kit hands a gesture to\n * whichever sensor's activator claims it first — `pointerdown` always fires\n * before `touchstart`, so a plain PointerSensor would swallow every touch and\n * the TouchSensor's press-and-hold would never run. Declining touch pointers\n * here leaves them to the TouchSensor, which is what lets a finger scroll the\n * palette, the layers tree and the canvas without picking anything up.\n */\nclass NonTouchPointerSensor extends PointerSensor {\n static activators: typeof PointerSensor.activators =\n PointerSensor.activators.map((activator) => ({\n ...activator,\n handler: (event, options) =>\n event.nativeEvent.pointerType !== 'touch' &&\n activator.handler(event, options),\n }))\n}\n\n/**\n * A mouse or pen drag starts after a few pixels of travel, so a click on a\n * drag handle (the overlay's move button, a palette card) stays a click.\n */\nconst POINTER_ACTIVATION = { distance: 6 }\n\n/**\n * A finger drag starts after a short hold; moving further than the tolerance\n * before then is a scroll, and the drag never starts.\n */\nconst TOUCH_ACTIVATION = { delay: 250, tolerance: 8 }\n\nexport interface BesignerDndContextProps<BackendContext, BackendOptions> {\n children?: JSX.Children\n backend?: BackendFactory\n context?: BackendContext\n options?: BackendOptions\n debugMode?: boolean\n}\n\nexport function BesignerDndContext<T, U>(props: BesignerDndContextProps<T, U>) {\n const { children, options, ...rest } = props\n const opts = {\n enableTouchEvents: true,\n enableMouseEvents: true,\n enableKeyboardEvents: true,\n delay: 0,\n delayTouchStart: 0,\n delayMouseStart: 0,\n touchSlop: 0,\n ...options,\n }\n\n const sensors = useSensors(\n useSensor(NonTouchPointerSensor, {\n activationConstraint: POINTER_ACTIVATION,\n }),\n useSensor(TouchSensor, { activationConstraint: TOUCH_ACTIVATION }),\n useSensor(KeyboardSensor),\n )\n\n return (\n <DndProvider backend={HTML5Backend} options={opts} {...rest} debugMode>\n <DndContext\n sensors={sensors}\n modifiers={[snapDraggingToCursor]}\n collisionDetection={pointerWithin}\n measuring={{\n droppable: {\n strategy: MeasuringStrategy.Always,\n },\n }}\n >\n {children}\n </DndContext>\n </DndProvider>\n )\n}\nBesignerDndContext.displayName = 'BesignerDndContext'\nBesignerDndContext.aglyn = true\n\nexport default BesignerDndContext\n"],"names":["DndContext","KeyboardSensor","MeasuringStrategy","PointerSensor","pointerWithin","TouchSensor","useSensor","useSensors","getEventCoordinates","DndProvider","HTML5Backend","snapDraggingToCursor","activatorEvent","draggingNodeRect","transform","activatorCoordinates","offsetX","x","left","offsetY","y","top","NonTouchPointerSensor","activators","map","activator","handler","event","options","nativeEvent","pointerType","POINTER_ACTIVATION","distance","TOUCH_ACTIVATION","delay","tolerance","BesignerDndContext","props","children","rest","opts","enableTouchEvents","enableMouseEvents","enableKeyboardEvents","delayTouchStart","delayMouseStart","touchSlop","sensors","activationConstraint","backend","debugMode","modifiers","collisionDetection","measuring","droppable","strategy","Always","displayName","aglyn"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC;;;AAGD,SACEA,UAAU,EACVC,cAAc,EACdC,iBAAiB,EACjBC,aAAa,EACbC,aAAa,EACbC,WAAW,EACXC,SAAS,EACTC,UAAU,QACL,gBAAe;AACtB,SAASC,mBAAmB,QAAQ,qBAAoB;AAExD,SAASC,WAAW,QAAQ,YAAW;AACvC,SAASC,YAAY,QAAQ,0BAAyB;AAEtD,OAAO,MAAMC,uBAAiC,CAAC,EAC7CC,cAAc,EACdC,gBAAgB,EAChBC,SAAS,EACV;IACC,IAAID,oBAAoBD,gBAAgB;QACtC,MAAMG,uBAAuBP,oBAAoBI;QACjD,IAAI,CAACG,sBAAsB,OAAOD;QAElC,MAAME,UAAUD,qBAAqBE,CAAC,GAAGJ,iBAAiBK,IAAI;QAC9D,MAAMC,UAAUJ,qBAAqBK,CAAC,GAAGP,iBAAiBQ,GAAG;QAE7D,OAAO,aACFP;YACHG,GAAGH,UAAUG,CAAC,GAAGD,UAAU;YAC3BI,GAAGN,UAAUM,CAAC,GAAGD,UAAU;;IAE/B;IAEA,OAAOL;AACT,EAAC;AACD;;;;;;;CAOC,GACD,IAAA,AAAMQ,wBAAN,MAAMA,8BAA8BnB;AAQpC;AARMmB,sBACGC,aACLpB,cAAcoB,UAAU,CAACC,GAAG,CAAC,CAACC,YAAe,aACxCA;QACHC,SAAS,CAACC,OAAOC,UACfD,MAAME,WAAW,CAACC,WAAW,KAAK,WAClCL,UAAUC,OAAO,CAACC,OAAOC;;AAIjC;;;CAGC,GACD,MAAMG,qBAAqB;IAAEC,UAAU;AAAE;AAEzC;;;CAGC,GACD,MAAMC,mBAAmB;IAAEC,OAAO;IAAKC,WAAW;AAAE;AAUpD,OAAO,SAASC,mBAAyBC,KAAoC;IAC3E,MAAM,EAAEC,QAAQ,EAAEV,OAAO,EAAW,GAAGS,OAATE,wCAASF;;;;IACvC,MAAMG,OAAO;QACXC,mBAAmB;QACnBC,mBAAmB;QACnBC,sBAAsB;QACtBT,OAAO;QACPU,iBAAiB;QACjBC,iBAAiB;QACjBC,WAAW;OACRlB;IAGL,MAAMmB,UAAUxC,WACdD,UAAUgB,uBAAuB;QAC/B0B,sBAAsBjB;IACxB,IACAzB,UAAUD,aAAa;QAAE2C,sBAAsBf;IAAiB,IAChE3B,UAAUL;IAGZ,qBACE,KAACQ;QAAYwC,SAASvC;QAAckB,SAASY;OAAUD;QAAMW,SAAS;kBACpE,cAAA,KAAClD;YACC+C,SAASA;YACTI,WAAW;gBAACxC;aAAqB;YACjCyC,oBAAoBhD;YACpBiD,WAAW;gBACTC,WAAW;oBACTC,UAAUrD,kBAAkBsD,MAAM;gBACpC;YACF;sBAEClB;;;AAIT;AACAF,mBAAmBqB,WAAW,GAAG;AACjCrB,mBAAmBsB,KAAK,GAAG;AAE3B,eAAetB,mBAAkB"}
@@ -22,6 +22,7 @@ import { DragOverlay, useDndMonitor } from "@dnd-kit/core";
22
22
  import { Box, Grid, Stack } from "@mui/material";
23
23
  import { Observer, observer } from "mobx-react-lite";
24
24
  import { useEffect } from "react";
25
+ import { createPortal } from "react-dom";
25
26
  import { useElementDrawerContext } from "../contexts/element-drawer-context.js";
26
27
  import useDetailHoverIntent from "../hooks/use-detail-hover-intent.js";
27
28
  import usePickerFilter from "../hooks/use-picker-filter.js";
@@ -173,15 +174,16 @@ export const ComponentAccordionList = observer((props)=>{
173
174
  opacity: 0.5
174
175
  } : {}
175
176
  }, draggable.listeners)),
176
- /*#__PURE__*/ _jsx(DragOverlay, {
177
+ /*#__PURE__*/ createPortal(/*#__PURE__*/ _jsx(DragOverlay, {
177
178
  dropAnimation: null,
179
+ zIndex: 9999,
178
180
  children: draggable.isDragging && /*#__PURE__*/ _jsx(NodeCard, {
179
181
  node: node,
180
182
  sx: {
181
183
  zIndex: 9999
182
184
  }
183
185
  })
184
- })
186
+ }), document.body)
185
187
  ]
186
188
  })
187
189
  })
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../../libs/besigner/feature/designer/src/lib/components/component-accordion-list.tsx"],"sourcesContent":["/**\n * @license\n * Copyright 2023 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n REUSABLE_COMPONENT_CATEGORY,\n REUSABLE_EMAIL_BLOCK_CATEGORY,\n} from '@aglyn/aglyn'\nimport { DragType } from '@aglyn/besigner'\nimport { mergeRefs } from '@aglyn/shared-ui-jsx'\nimport { DragOverlay, useDndMonitor } from '@dnd-kit/core'\nimport { Box, Grid, Stack } from '@mui/material'\nimport { Observer, observer } from 'mobx-react-lite'\nimport { useEffect } from 'react'\nimport { useElementDrawerContext } from '../contexts/element-drawer-context'\nimport useDetailHoverIntent from '../hooks/use-detail-hover-intent'\nimport usePickerFilter from '../hooks/use-picker-filter'\nimport useVisibleComponentCategories from '../hooks/use-visible-component-categories'\nimport { besignerDocsUrl } from '../utils/docs-help'\nimport { AccordionListComponent } from './accordion-list.component'\nimport Draggable from './dnd/draggable'\nimport ElementDetailOverlay from './element-detail-overlay.component'\nimport EmptyResults from './empty-results'\nimport NodeCard, { type NodeCardItemData } from './node-card'\nimport PickerSearchField from './picker-search-field'\n\nexport type ComponentGridGroupItemData = {\n $id: string\n label: string\n items: NodeCardItemData[]\n}\n\nNodeCard.displayName = 'NodeCard'\n\ninterface ComponentAccordionListProp {}\n\nexport const ComponentAccordionList = observer(\n (props: ComponentAccordionListProp) => {\n const { ...rest } = props\n const allItems = useVisibleComponentCategories()\n\n // The SAME search the Choose-element dialog runs (AGL-2486). The panel\n // had no search at all; giving it a second implementation would mean two\n // pickers disagreeing about what `icon` matches, which is worse than one\n // of them having none.\n const { filter, items, handleFilterChange } = usePickerFilter(allItems)\n\n // Hover previews, click PINS, and the pin outranks the pointer — which\n // is what makes the floating panel clickable at all. See\n // `useDetailHoverIntent` for why each half is load-bearing.\n const detail = useDetailHoverIntent<NodeCardItemData>()\n\n // The panel floats over the CANVAS, which is exactly where a dragged\n // element is going. It leaves the drop path on drag START — waiting for\n // the drop would leave it sitting under the pointer for the whole\n // gesture — and stays suspended until the drag ends so the cards the\n // pointer crosses on the way out cannot re-open it.\n useDndMonitor({\n onDragStart: detail.suspend,\n onDragEnd: detail.resume,\n onDragCancel: detail.resume,\n })\n\n // A modal opening over the panel is a context change, and a pinned\n // detail has no business outliving it.\n const drawerOpen = useElementDrawerContext()?.open\n useEffect(() => {\n if (drawerOpen) detail.dismiss()\n }, [drawerOpen, detail])\n\n return (\n <Stack sx={{ height: 1, minHeight: 0 }}>\n <Box\n sx={{\n display: 'flex',\n alignItems: 'center',\n px: 1,\n py: 0.5,\n borderBottom: 1,\n borderColor: 'divider',\n // The panel is a scrolling column; the search must stay reachable\n // without scrolling back to the top of ~45 elements.\n position: 'sticky',\n top: 0,\n zIndex: 6,\n backgroundColor: 'surface.main',\n }}\n >\n <PickerSearchField value={filter} onChange={handleFilterChange} />\n </Box>\n {!items?.length ? (\n <EmptyResults sx={{ minHeight: 200 }} />\n ) : (\n // The grid scrolls; the detail region below it does not, so the\n // description stays put while you browse.\n // Scrolling moves the card the panel is anchored to, so a pinned\n // panel would end up pointing at whatever slid into its place.\n <Box\n sx={{ flex: 1, minHeight: 0, overflowY: 'auto' }}\n onScroll={detail.dismiss}\n >\n <AccordionListComponent\n // No `key` remount to force the results group open (AGL-2486).\n // Keying on the filter flipped one render too EARLY — the query\n // changes synchronously, the results group only exists after\n // fuse.js loads — so the remount reseeded from the categories\n // and the group that arrived next was collapsed. The list now\n // opens a group when it first appears, which is the same render\n // the group actually exists in.\n items={items}\n defaultExpanded={items.map((i) => i.$id)}\n getItemId={(item) => item?.$id}\n // Only the host's own components group carries help (AGL-2167).\n // The built-in groups are self-evident from their contents; this one\n // is the only group whose items the user has to CREATE before it\n // holds anything, and an empty-looking group explains nothing.\n getItemHelp={(item) =>\n item?.$id === REUSABLE_COMPONENT_CATEGORY\n ? {\n title: 'Your components',\n excerpt:\n 'Sections you promoted into reusable components. Drop one to place an instance — edit the component once and every instance follows.',\n href: besignerDocsUrl(\n 'reusableComponents',\n '#insert-instances',\n ),\n }\n : // The same group in an email's drawer (AGL-3287), which\n // is just as empty until the site saves a block for it.\n item?.$id === REUSABLE_EMAIL_BLOCK_CATEGORY\n ? {\n title: REUSABLE_EMAIL_BLOCK_CATEGORY,\n excerpt:\n 'Headers, footers and other blocks you saved for emails. Drop one into this email — change the block once and every email using it follows.',\n href: besignerDocsUrl(\n 'reusableComponents',\n '#reusable-email-blocks',\n ),\n }\n : undefined\n }\n onRenderSummary={({ item }) => (\n <Observer>{() => <>{item?.label}</>}</Observer>\n )}\n AccordionDetailsProps={{\n sx: { overflowX: 'hidden' },\n }}\n onRenderDetail={({ item }) => (\n <Observer>\n {() => (\n <Box>\n <Grid spacing={2} container sx={{ overflowX: 'hidden' }}>\n {item?.items?.map((node, index) => (\n <Grid\n key={node?.$id ?? index}\n size={6}\n onMouseEnter={(e) =>\n detail.open(node, e.currentTarget as HTMLElement)\n }\n onMouseLeave={detail.scheduleClose}\n onClick={(e) =>\n detail.togglePin(\n node,\n e.currentTarget as HTMLElement,\n )\n }\n >\n <Draggable\n node={node}\n type={DragType.PRESET}\n idSuffix={item?.$id}\n >\n {({ draggable, node, forwardRef }) => (\n <>\n <NodeCard\n ref={mergeRefs(\n forwardRef,\n draggable.setNodeRef,\n )}\n node={node as any}\n style={\n draggable.isDragging\n ? { opacity: 0.5 }\n : {}\n }\n {...draggable.listeners}\n />\n <DragOverlay dropAnimation={null}>\n {draggable.isDragging && (\n <NodeCard\n node={node as any}\n sx={{ zIndex: 9999 }}\n />\n )}\n </DragOverlay>\n </>\n )}\n </Draggable>\n </Grid>\n ))}\n </Grid>\n </Box>\n )}\n </Observer>\n )}\n {...rest}\n />\n </Box>\n )}\n <ElementDetailOverlay\n item={detail.active?.item}\n anchor={detail.active?.anchor ?? null}\n pinned={detail.isPinned}\n onPointerEnter={detail.keepOpen}\n onPointerLeave={detail.scheduleClose}\n onDismiss={detail.dismiss}\n />\n </Stack>\n )\n },\n)\nComponentAccordionList.displayName = 'ComponentAccordionList'\n\nexport default ComponentAccordionList\n"],"names":["REUSABLE_COMPONENT_CATEGORY","REUSABLE_EMAIL_BLOCK_CATEGORY","DragType","mergeRefs","DragOverlay","useDndMonitor","Box","Grid","Stack","Observer","observer","useEffect","useElementDrawerContext","useDetailHoverIntent","usePickerFilter","useVisibleComponentCategories","besignerDocsUrl","AccordionListComponent","Draggable","ElementDetailOverlay","EmptyResults","NodeCard","PickerSearchField","displayName","ComponentAccordionList","props","detail","rest","allItems","filter","items","handleFilterChange","onDragStart","suspend","onDragEnd","resume","onDragCancel","drawerOpen","open","dismiss","sx","height","minHeight","display","alignItems","px","py","borderBottom","borderColor","position","top","zIndex","backgroundColor","value","onChange","length","flex","overflowY","onScroll","defaultExpanded","map","i","$id","getItemId","item","getItemHelp","title","excerpt","href","undefined","onRenderSummary","label","AccordionDetailsProps","overflowX","onRenderDetail","spacing","container","node","index","size","onMouseEnter","e","currentTarget","onMouseLeave","scheduleClose","onClick","togglePin","type","PRESET","idSuffix","draggable","forwardRef","ref","setNodeRef","style","isDragging","opacity","listeners","dropAnimation","active","anchor","pinned","isPinned","onPointerEnter","keepOpen","onPointerLeave","onDismiss"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../../../../libs/besigner/feature/designer/src/lib/components/component-accordion-list.tsx"],"sourcesContent":["/**\n * @license\n * Copyright 2023 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n REUSABLE_COMPONENT_CATEGORY,\n REUSABLE_EMAIL_BLOCK_CATEGORY,\n} from '@aglyn/aglyn'\nimport { DragType } from '@aglyn/besigner'\nimport { mergeRefs } from '@aglyn/shared-ui-jsx'\nimport { DragOverlay, useDndMonitor } from '@dnd-kit/core'\nimport { Box, Grid, Stack } from '@mui/material'\nimport { Observer, observer } from 'mobx-react-lite'\nimport { useEffect } from 'react'\nimport { createPortal } from 'react-dom'\nimport { useElementDrawerContext } from '../contexts/element-drawer-context'\nimport useDetailHoverIntent from '../hooks/use-detail-hover-intent'\nimport usePickerFilter from '../hooks/use-picker-filter'\nimport useVisibleComponentCategories from '../hooks/use-visible-component-categories'\nimport { besignerDocsUrl } from '../utils/docs-help'\nimport { AccordionListComponent } from './accordion-list.component'\nimport Draggable from './dnd/draggable'\nimport ElementDetailOverlay from './element-detail-overlay.component'\nimport EmptyResults from './empty-results'\nimport NodeCard, { type NodeCardItemData } from './node-card'\nimport PickerSearchField from './picker-search-field'\n\nexport type ComponentGridGroupItemData = {\n $id: string\n label: string\n items: NodeCardItemData[]\n}\n\nNodeCard.displayName = 'NodeCard'\n\ninterface ComponentAccordionListProp {}\n\nexport const ComponentAccordionList = observer(\n (props: ComponentAccordionListProp) => {\n const { ...rest } = props\n const allItems = useVisibleComponentCategories()\n\n // The SAME search the Choose-element dialog runs (AGL-2486). The panel\n // had no search at all; giving it a second implementation would mean two\n // pickers disagreeing about what `icon` matches, which is worse than one\n // of them having none.\n const { filter, items, handleFilterChange } = usePickerFilter(allItems)\n\n // Hover previews, click PINS, and the pin outranks the pointer — which\n // is what makes the floating panel clickable at all. See\n // `useDetailHoverIntent` for why each half is load-bearing.\n const detail = useDetailHoverIntent<NodeCardItemData>()\n\n // The panel floats over the CANVAS, which is exactly where a dragged\n // element is going. It leaves the drop path on drag START — waiting for\n // the drop would leave it sitting under the pointer for the whole\n // gesture — and stays suspended until the drag ends so the cards the\n // pointer crosses on the way out cannot re-open it.\n useDndMonitor({\n onDragStart: detail.suspend,\n onDragEnd: detail.resume,\n onDragCancel: detail.resume,\n })\n\n // A modal opening over the panel is a context change, and a pinned\n // detail has no business outliving it.\n const drawerOpen = useElementDrawerContext()?.open\n useEffect(() => {\n if (drawerOpen) detail.dismiss()\n }, [drawerOpen, detail])\n\n return (\n <Stack sx={{ height: 1, minHeight: 0 }}>\n <Box\n sx={{\n display: 'flex',\n alignItems: 'center',\n px: 1,\n py: 0.5,\n borderBottom: 1,\n borderColor: 'divider',\n // The panel is a scrolling column; the search must stay reachable\n // without scrolling back to the top of ~45 elements.\n position: 'sticky',\n top: 0,\n zIndex: 6,\n backgroundColor: 'surface.main',\n }}\n >\n <PickerSearchField value={filter} onChange={handleFilterChange} />\n </Box>\n {!items?.length ? (\n <EmptyResults sx={{ minHeight: 200 }} />\n ) : (\n // The grid scrolls; the detail region below it does not, so the\n // description stays put while you browse.\n // Scrolling moves the card the panel is anchored to, so a pinned\n // panel would end up pointing at whatever slid into its place.\n <Box\n sx={{ flex: 1, minHeight: 0, overflowY: 'auto' }}\n onScroll={detail.dismiss}\n >\n <AccordionListComponent\n // No `key` remount to force the results group open (AGL-2486).\n // Keying on the filter flipped one render too EARLY — the query\n // changes synchronously, the results group only exists after\n // fuse.js loads — so the remount reseeded from the categories\n // and the group that arrived next was collapsed. The list now\n // opens a group when it first appears, which is the same render\n // the group actually exists in.\n items={items}\n defaultExpanded={items.map((i) => i.$id)}\n getItemId={(item) => item?.$id}\n // Only the host's own components group carries help (AGL-2167).\n // The built-in groups are self-evident from their contents; this one\n // is the only group whose items the user has to CREATE before it\n // holds anything, and an empty-looking group explains nothing.\n getItemHelp={(item) =>\n item?.$id === REUSABLE_COMPONENT_CATEGORY\n ? {\n title: 'Your components',\n excerpt:\n 'Sections you promoted into reusable components. Drop one to place an instance — edit the component once and every instance follows.',\n href: besignerDocsUrl(\n 'reusableComponents',\n '#insert-instances',\n ),\n }\n : // The same group in an email's drawer (AGL-3287), which\n // is just as empty until the site saves a block for it.\n item?.$id === REUSABLE_EMAIL_BLOCK_CATEGORY\n ? {\n title: REUSABLE_EMAIL_BLOCK_CATEGORY,\n excerpt:\n 'Headers, footers and other blocks you saved for emails. Drop one into this email — change the block once and every email using it follows.',\n href: besignerDocsUrl(\n 'reusableComponents',\n '#reusable-email-blocks',\n ),\n }\n : undefined\n }\n onRenderSummary={({ item }) => (\n <Observer>{() => <>{item?.label}</>}</Observer>\n )}\n AccordionDetailsProps={{\n sx: { overflowX: 'hidden' },\n }}\n onRenderDetail={({ item }) => (\n <Observer>\n {() => (\n <Box>\n <Grid spacing={2} container sx={{ overflowX: 'hidden' }}>\n {item?.items?.map((node, index) => (\n <Grid\n key={node?.$id ?? index}\n size={6}\n onMouseEnter={(e) =>\n detail.open(node, e.currentTarget as HTMLElement)\n }\n onMouseLeave={detail.scheduleClose}\n onClick={(e) =>\n detail.togglePin(\n node,\n e.currentTarget as HTMLElement,\n )\n }\n >\n <Draggable\n node={node}\n type={DragType.PRESET}\n idSuffix={item?.$id}\n >\n {({ draggable, node, forwardRef }) => (\n <>\n <NodeCard\n ref={mergeRefs(\n forwardRef,\n draggable.setNodeRef,\n )}\n node={node as any}\n style={\n draggable.isDragging\n ? { opacity: 0.5 }\n : {}\n }\n {...draggable.listeners}\n />\n {/* Portaled: below `md` this list sits in\n an overlay drawer that hides while a\n drag is in flight, and the card under\n the finger must outlive it. */}\n {createPortal(\n <DragOverlay dropAnimation={null} zIndex={9999}>\n {draggable.isDragging && (\n <NodeCard\n node={node as any}\n sx={{ zIndex: 9999 }}\n />\n )}\n </DragOverlay>,\n document.body,\n )}\n </>\n )}\n </Draggable>\n </Grid>\n ))}\n </Grid>\n </Box>\n )}\n </Observer>\n )}\n {...rest}\n />\n </Box>\n )}\n <ElementDetailOverlay\n item={detail.active?.item}\n anchor={detail.active?.anchor ?? null}\n pinned={detail.isPinned}\n onPointerEnter={detail.keepOpen}\n onPointerLeave={detail.scheduleClose}\n onDismiss={detail.dismiss}\n />\n </Stack>\n )\n },\n)\nComponentAccordionList.displayName = 'ComponentAccordionList'\n\nexport default ComponentAccordionList\n"],"names":["REUSABLE_COMPONENT_CATEGORY","REUSABLE_EMAIL_BLOCK_CATEGORY","DragType","mergeRefs","DragOverlay","useDndMonitor","Box","Grid","Stack","Observer","observer","useEffect","createPortal","useElementDrawerContext","useDetailHoverIntent","usePickerFilter","useVisibleComponentCategories","besignerDocsUrl","AccordionListComponent","Draggable","ElementDetailOverlay","EmptyResults","NodeCard","PickerSearchField","displayName","ComponentAccordionList","props","detail","rest","allItems","filter","items","handleFilterChange","onDragStart","suspend","onDragEnd","resume","onDragCancel","drawerOpen","open","dismiss","sx","height","minHeight","display","alignItems","px","py","borderBottom","borderColor","position","top","zIndex","backgroundColor","value","onChange","length","flex","overflowY","onScroll","defaultExpanded","map","i","$id","getItemId","item","getItemHelp","title","excerpt","href","undefined","onRenderSummary","label","AccordionDetailsProps","overflowX","onRenderDetail","spacing","container","node","index","size","onMouseEnter","e","currentTarget","onMouseLeave","scheduleClose","onClick","togglePin","type","PRESET","idSuffix","draggable","forwardRef","ref","setNodeRef","style","isDragging","opacity","listeners","dropAnimation","document","body","active","anchor","pinned","isPinned","onPointerEnter","keepOpen","onPointerLeave","onDismiss"],"mappings":"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"}
@@ -18,7 +18,7 @@ import { _ as _object_without_properties_loose } from "@swc/helpers/_/_object_wi
18
18
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
19
19
  import { ICON_VARIANT_CLOSE, ICON_VARIANT_FILTER } from "@aglyn/shared-data-enums";
20
20
  import { MdiIcon } from "@aglyn/shared-ui-jsx";
21
- import { AppBar, Box, Button, Collapse, Dialog, DialogContent, Divider, IconButton, Slide, Toolbar, Typography } from "@mui/material";
21
+ import { AppBar, Box, Button, Collapse, Dialog, DialogActions, DialogContent, Divider, IconButton, Slide, Toolbar, Typography, useMediaQuery, useTheme } from "@mui/material";
22
22
  import { Observer, observer } from "mobx-react-lite";
23
23
  import { forwardRef, useCallback, useState } from "react";
24
24
  import usePickerFilter from "../hooks/use-picker-filter.js";
@@ -75,6 +75,10 @@ export const ComponentPicker = observer(/*#__PURE__*/ forwardRef((props, forward
75
75
  const allItems = useVisibleComponentCategories();
76
76
  const [filterOpen, setFilterOpen] = useState(false);
77
77
  const [selected, setSelected] = useState(null);
78
+ // A phone has no room for the paper's margins: the picker takes the
79
+ // whole screen there, with its close button where the toolbar puts it.
80
+ const theme = useTheme();
81
+ const fullScreen = useMediaQuery(theme.breakpoints.down('sm'));
78
82
  const clearSelected = useCallback(()=>setSelected(null), []);
79
83
  // The SAME search the Elements panel runs (AGL-2486). Both surfaces read
80
84
  // one hook so a query cannot mean two different things depending on
@@ -117,6 +121,7 @@ export const ComponentPicker = observer(/*#__PURE__*/ forwardRef((props, forward
117
121
  // at this one.
118
122
  maxWidth: "xl",
119
123
  fullWidth: true,
124
+ fullScreen: fullScreen,
120
125
  slots: {
121
126
  transition: Transition
122
127
  }
@@ -345,7 +350,11 @@ export const ComponentPicker = observer(/*#__PURE__*/ forwardRef((props, forward
345
350
  sx: {
346
351
  p: 1.5,
347
352
  borderTop: 1,
348
- borderColor: 'divider'
353
+ borderColor: 'divider',
354
+ display: {
355
+ xs: 'none',
356
+ md: 'block'
357
+ }
349
358
  },
350
359
  children: /*#__PURE__*/ _jsx(Button, {
351
360
  fullWidth: true,
@@ -358,6 +367,37 @@ export const ComponentPicker = observer(/*#__PURE__*/ forwardRef((props, forward
358
367
  ]
359
368
  })
360
369
  ]
370
+ }),
371
+ /*#__PURE__*/ _jsxs(DialogActions, {
372
+ sx: {
373
+ display: {
374
+ xs: 'flex',
375
+ md: 'none'
376
+ },
377
+ gap: 1,
378
+ borderTop: 1,
379
+ borderColor: 'divider'
380
+ },
381
+ children: [
382
+ /*#__PURE__*/ _jsx(Typography, {
383
+ variant: "body2",
384
+ noWrap: true,
385
+ sx: {
386
+ flex: 1,
387
+ minWidth: 0
388
+ },
389
+ children: selected ? describeElement(selected).name : 'Choose an element'
390
+ }),
391
+ /*#__PURE__*/ _jsx(Button, {
392
+ variant: "contained",
393
+ disabled: !selected,
394
+ onClick: handleConfirm,
395
+ sx: {
396
+ flexShrink: 0
397
+ },
398
+ children: 'Confirm'
399
+ })
400
+ ]
361
401
  })
362
402
  ]
363
403
  }));