@atelier-ui/react 0.2.1 → 0.2.3
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.
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
## 0.2.3 (2026-07-22)
|
|
2
|
+
|
|
3
|
+
### 🚀 Features
|
|
4
|
+
|
|
5
|
+
- **a11y:** extend cross-framework a11y-parity gate to Dialog, Menu, Tabs, Alert ([4e6c297](https://github.com/DominikPieper/atelier-ui/commit/4e6c297))
|
|
6
|
+
|
|
7
|
+
### ❤️ Thank You
|
|
8
|
+
|
|
9
|
+
- Dominik Pieper @DominikPieper
|
|
10
|
+
|
|
11
|
+
## 0.2.2 (2026-07-22)
|
|
12
|
+
|
|
13
|
+
This was a version bump only for react to align it with other projects, there were no code changes.
|
|
14
|
+
|
|
1
15
|
## 0.2.1 (2026-07-21)
|
|
2
16
|
|
|
3
17
|
This was a version bump only for react to align it with other projects, there were no code changes.
|
package/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"atl-menu.d.ts","sourceRoot":"","sources":["../../../../../../libs/react/src/lib/menu/atl-menu.tsx"],"names":[],"mappings":"AAAA,OAAO,EAML,SAAS,EACT,cAAc,EACd,SAAS,EACV,MAAM,OAAO,CAAC;AACf,OAAO,KAAK,EACV,WAAW,EACX,eAAe,EAChB,MAAM,SAAS,CAAC;AACjB,OAAO,gBAAgB,CAAC;AAQxB;;GAEG;AACH,MAAM,WAAW,YAAa,SAAQ,cAAc,CAAC,cAAc,CAAC,EAAE,WAAW;IAC/E;;OAEG;IACH,OAAO,CAAC,EAAE,SAAS,GAAG,SAAS,CAAC;IAChC;;OAEG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAED;;GAEG;AACH,wBAAgB,OAAO,CAAC,EAAE,OAAmB,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,IAAI,EAAE,EAAE,YAAY,+BAO1F;AAED;;GAEG;AACH,MAAM,WAAW,gBACf,SAAQ,cAAc,CAAC,iBAAiB,CAAC,EACvC,eAAe;IACjB;;OAEG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;IACzB;;OAEG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,EAC1B,QAAgB,EAChB,WAAW,EACX,QAAQ,EACR,SAAS,EACT,OAAO,EACP,GAAG,IAAI,EACR,EAAE,gBAAgB,+BAyBlB;AAED;;GAEG;AACH,wBAAgB,gBAAgB,gCAE/B;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC;;OAEG;IACH,IAAI,EAAE,SAAS,CAAC;IAChB;;OAEG;IACH,QAAQ,EAAE,CAAC,KAAK,EAAE;QAChB,OAAO,EAAE,MAAM,IAAI,CAAC;QACpB,GAAG,EAAE,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;KACpC,KAAK,SAAS,CAAC;CACjB;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,mBAAmB,+
|
|
1
|
+
{"version":3,"file":"atl-menu.d.ts","sourceRoot":"","sources":["../../../../../../libs/react/src/lib/menu/atl-menu.tsx"],"names":[],"mappings":"AAAA,OAAO,EAML,SAAS,EACT,cAAc,EACd,SAAS,EACV,MAAM,OAAO,CAAC;AACf,OAAO,KAAK,EACV,WAAW,EACX,eAAe,EAChB,MAAM,SAAS,CAAC;AACjB,OAAO,gBAAgB,CAAC;AAQxB;;GAEG;AACH,MAAM,WAAW,YAAa,SAAQ,cAAc,CAAC,cAAc,CAAC,EAAE,WAAW;IAC/E;;OAEG;IACH,OAAO,CAAC,EAAE,SAAS,GAAG,SAAS,CAAC;IAChC;;OAEG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAED;;GAEG;AACH,wBAAgB,OAAO,CAAC,EAAE,OAAmB,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,IAAI,EAAE,EAAE,YAAY,+BAO1F;AAED;;GAEG;AACH,MAAM,WAAW,gBACf,SAAQ,cAAc,CAAC,iBAAiB,CAAC,EACvC,eAAe;IACjB;;OAEG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;IACzB;;OAEG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,EAC1B,QAAgB,EAChB,WAAW,EACX,QAAQ,EACR,SAAS,EACT,OAAO,EACP,GAAG,IAAI,EACR,EAAE,gBAAgB,+BAyBlB;AAED;;GAEG;AACH,wBAAgB,gBAAgB,gCAE/B;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC;;OAEG;IACH,IAAI,EAAE,SAAS,CAAC;IAChB;;OAEG;IACH,QAAQ,EAAE,CAAC,KAAK,EAAE;QAChB,OAAO,EAAE,MAAM,IAAI,CAAC;QACpB,GAAG,EAAE,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;KACpC,KAAK,SAAS,CAAC;CACjB;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,mBAAmB,+BAsDrE"}
|
package/src/lib/menu/atl-menu.js
CHANGED
|
@@ -39,6 +39,16 @@ export function AtlMenuTrigger({ menu, children }) {
|
|
|
39
39
|
const [open, setOpen] = useState(false);
|
|
40
40
|
const triggerRef = useRef(null);
|
|
41
41
|
const menuRef = useRef(null);
|
|
42
|
+
// Menu-button ARIA on the trigger element itself (the render prop binds the
|
|
43
|
+
// ref to it) — mirrors what the CDK menu trigger does in the Angular adapter,
|
|
44
|
+
// so consumers get correct semantics without wiring attributes by hand.
|
|
45
|
+
useEffect(() => {
|
|
46
|
+
const el = triggerRef.current;
|
|
47
|
+
if (!el)
|
|
48
|
+
return;
|
|
49
|
+
el.setAttribute('aria-haspopup', 'menu');
|
|
50
|
+
el.setAttribute('aria-expanded', String(open));
|
|
51
|
+
}, [open]);
|
|
42
52
|
useEffect(() => {
|
|
43
53
|
if (!open)
|
|
44
54
|
return;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"atl-menu.js","sourceRoot":"","sources":["../../../../../../libs/react/src/lib/menu/atl-menu.tsx"],"names":[],"mappings":";AAAA,OAAO,EACL,aAAa,EACb,UAAU,EACV,MAAM,EACN,QAAQ,EACR,SAAS,GAIV,MAAM,OAAO,CAAC;AAKf,OAAO,gBAAgB,CAAC;AAMxB,MAAM,WAAW,GAAG,aAAa,CAAmB,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,SAAS,EAAE,CAAC,CAAC;AAgBhF;;GAEG;AACH,MAAM,UAAU,OAAO,CAAC,EAAE,OAAO,GAAG,SAAS,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,IAAI,EAAgB;IACzF,MAAM,OAAO,GAAG,CAAC,UAAU,EAAE,WAAW,OAAO,EAAE,EAAE,SAAS,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACxF,OAAO,CACL,cAAK,SAAS,EAAE,OAAO,EAAE,IAAI,EAAC,MAAM,KAAK,IAAI,YAC1C,QAAQ,GACL,CACP,CAAC;AACJ,CAAC;AAsBD;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,EAC1B,QAAQ,GAAG,KAAK,EAChB,WAAW,EACX,QAAQ,EACR,SAAS,EACT,OAAO,EACP,GAAG,IAAI,EACU;IACjB,MAAM,GAAG,GAAG,UAAU,CAAC,WAAW,CAAC,CAAC;IACpC,MAAM,OAAO,GAAG,CAAC,eAAe,EAAE,QAAQ,IAAI,aAAa,EAAE,SAAS,CAAC;SACpE,MAAM,CAAC,OAAO,CAAC;SACf,IAAI,CAAC,GAAG,CAAC,CAAC;IAEb,MAAM,WAAW,GAAG,CAAC,CAAsC,EAAE,EAAE;QAC7D,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,WAAW,EAAE,EAAE,CAAC;YAChB,GAAG,CAAC,KAAK,EAAE,CAAC;YACZ,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC;QACf,CAAC;IACH,CAAC,CAAC;IAEF,OAAO,CACL,iBACE,SAAS,EAAE,OAAO,EAClB,IAAI,EAAC,UAAU,EACf,QAAQ,EAAE,QAAQ,EAClB,OAAO,EAAE,WAAW,KAChB,IAAI,YAEP,QAAQ,GACF,CACV,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB;IAC9B,OAAO,aAAI,SAAS,EAAC,oBAAoB,GAAG,CAAC;AAC/C,CAAC;AAmBD;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAuB;IACpE,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IACxC,MAAM,UAAU,GAAG,MAAM,CAAc,IAAI,CAAC,CAAC;IAC7C,MAAM,OAAO,GAAG,MAAM,CAAiB,IAAI,CAAC,CAAC;IAE7C,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,IAAI;YAAE,OAAO;QAElB,MAAM,kBAAkB,GAAG,CAAC,CAAa,EAAE,EAAE;YAC3C,IACE,CAAC,OAAO,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC,MAAc,CAAC;gBAC5C,CAAC,UAAU,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC,MAAc,CAAC,EAC/C,CAAC;gBACD,OAAO,CAAC,KAAK,CAAC,CAAC;YACjB,CAAC;QACH,CAAC,CAAC;QAEF,MAAM,aAAa,GAAG,CAAC,CAA2B,EAAE,EAAE;YACpD,IAAI,CAAC,CAAC,GAAG,KAAK,QAAQ;gBAAE,OAAO,CAAC,KAAK,CAAC,CAAC;QACzC,CAAC,CAAC;QAEF,QAAQ,CAAC,gBAAgB,CAAC,WAAW,EAAE,kBAAkB,CAAC,CAAC;QAC3D,QAAQ,CAAC,gBAAgB,CAAC,SAAS,EAAE,aAAa,CAAC,CAAC;QACpD,OAAO,GAAG,EAAE;YACV,QAAQ,CAAC,mBAAmB,CAAC,WAAW,EAAE,kBAAkB,CAAC,CAAC;YAC9D,QAAQ,CAAC,mBAAmB,CAAC,SAAS,EAAE,aAAa,CAAC,CAAC;QACzD,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;IAEX,OAAO,CACL,KAAC,WAAW,CAAC,QAAQ,IAAC,KAAK,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,YAC1D,eACE,SAAS,EAAC,0BAA0B,EACpC,KAAK,EAAE,EAAE,QAAQ,EAAE,UAAU,EAAE,OAAO,EAAE,cAAc,EAAE,aAEvD,QAAQ,CAAC,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,UAAU,EAAE,CAAC,EAChE,IAAI,IAAI,CACP,cAAK,GAAG,EAAE,OAAO,EAAE,SAAS,EAAC,gBAAgB,YAC1C,IAAI,GACD,CACP,IACG,GACe,CACxB,CAAC;AACJ,CAAC","sourcesContent":["import {\n createContext,\n useContext,\n useRef,\n useState,\n useEffect,\n ReactNode,\n HTMLAttributes,\n RefObject,\n} from 'react';\nimport type {\n AtlMenuSpec,\n AtlMenuItemSpec,\n} from '../spec';\nimport './atl-menu.css';\n\ninterface MenuContextValue {\n close: () => void;\n}\n\nconst MenuContext = createContext<MenuContextValue>({ close: () => undefined });\n\n/**\n * Properties for the AtlMenu component.\n */\nexport interface AtlMenuProps extends HTMLAttributes<HTMLDivElement>, AtlMenuSpec {\n /**\n * The visual style variant of the menu.\n */\n variant?: 'default' | 'compact';\n /**\n * The menu items to be rendered.\n */\n children?: ReactNode;\n}\n\n/**\n * A menu component for displaying a list of choices.\n */\nexport function AtlMenu({ variant = 'default', children, className, ...rest }: AtlMenuProps) {\n const classes = ['atl-menu', `variant-${variant}`, className].filter(Boolean).join(' ');\n return (\n <div className={classes} role=\"menu\" {...rest}>\n {children}\n </div>\n );\n}\n\n/**\n * Properties for the AtlMenuItem component.\n */\nexport interface AtlMenuItemProps\n extends HTMLAttributes<HTMLButtonElement>,\n AtlMenuItemSpec {\n /**\n * Whether the menu item is disabled.\n */\n disabled?: boolean;\n /**\n * Callback triggered when the item is selected.\n */\n onTriggered?: () => void;\n /**\n * The content of the menu item.\n */\n children?: ReactNode;\n}\n\n/**\n * An individual item within a menu.\n */\nexport function AtlMenuItem({\n disabled = false,\n onTriggered,\n children,\n className,\n onClick,\n ...rest\n}: AtlMenuItemProps) {\n const ctx = useContext(MenuContext);\n const classes = ['atl-menu-item', disabled && 'is-disabled', className]\n .filter(Boolean)\n .join(' ');\n\n const handleClick = (e: React.MouseEvent<HTMLButtonElement>) => {\n if (!disabled) {\n onTriggered?.();\n ctx.close();\n onClick?.(e);\n }\n };\n\n return (\n <button\n className={classes}\n role=\"menuitem\"\n disabled={disabled}\n onClick={handleClick}\n {...rest}\n >\n {children}\n </button>\n );\n}\n\n/**\n * A separator for dividing groups of menu items.\n */\nexport function AtlMenuSeparator() {\n return <hr className=\"atl-menu-separator\" />;\n}\n\n/**\n * Properties for the AtlMenuTrigger component.\n */\nexport interface AtlMenuTriggerProps {\n /**\n * The menu to be displayed.\n */\n menu: ReactNode;\n /**\n * Render prop that provides trigger functionality.\n */\n children: (props: {\n onClick: () => void;\n ref: RefObject<HTMLElement | null>;\n }) => ReactNode;\n}\n\n/**\n * A component that manages the state of a menu and its trigger.\n */\nexport function AtlMenuTrigger({ menu, children }: AtlMenuTriggerProps) {\n const [open, setOpen] = useState(false);\n const triggerRef = useRef<HTMLElement>(null);\n const menuRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n if (!open) return;\n\n const handleOutsideClick = (e: MouseEvent) => {\n if (\n !menuRef.current?.contains(e.target as Node) &&\n !triggerRef.current?.contains(e.target as Node)\n ) {\n setOpen(false);\n }\n };\n\n const handleKeyDown = (e: globalThis.KeyboardEvent) => {\n if (e.key === 'Escape') setOpen(false);\n };\n\n document.addEventListener('mousedown', handleOutsideClick);\n document.addEventListener('keydown', handleKeyDown);\n return () => {\n document.removeEventListener('mousedown', handleOutsideClick);\n document.removeEventListener('keydown', handleKeyDown);\n };\n }, [open]);\n\n return (\n <MenuContext.Provider value={{ close: () => setOpen(false) }}>\n <div\n className=\"atl-menu-trigger-wrapper\"\n style={{ position: 'relative', display: 'inline-block' }}\n >\n {children({ onClick: () => setOpen((v) => !v), ref: triggerRef })}\n {open && (\n <div ref={menuRef} className=\"atl-menu-panel\">\n {menu}\n </div>\n )}\n </div>\n </MenuContext.Provider>\n );\n}\n"]}
|
|
1
|
+
{"version":3,"file":"atl-menu.js","sourceRoot":"","sources":["../../../../../../libs/react/src/lib/menu/atl-menu.tsx"],"names":[],"mappings":";AAAA,OAAO,EACL,aAAa,EACb,UAAU,EACV,MAAM,EACN,QAAQ,EACR,SAAS,GAIV,MAAM,OAAO,CAAC;AAKf,OAAO,gBAAgB,CAAC;AAMxB,MAAM,WAAW,GAAG,aAAa,CAAmB,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,SAAS,EAAE,CAAC,CAAC;AAgBhF;;GAEG;AACH,MAAM,UAAU,OAAO,CAAC,EAAE,OAAO,GAAG,SAAS,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,IAAI,EAAgB;IACzF,MAAM,OAAO,GAAG,CAAC,UAAU,EAAE,WAAW,OAAO,EAAE,EAAE,SAAS,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACxF,OAAO,CACL,cAAK,SAAS,EAAE,OAAO,EAAE,IAAI,EAAC,MAAM,KAAK,IAAI,YAC1C,QAAQ,GACL,CACP,CAAC;AACJ,CAAC;AAsBD;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,EAC1B,QAAQ,GAAG,KAAK,EAChB,WAAW,EACX,QAAQ,EACR,SAAS,EACT,OAAO,EACP,GAAG,IAAI,EACU;IACjB,MAAM,GAAG,GAAG,UAAU,CAAC,WAAW,CAAC,CAAC;IACpC,MAAM,OAAO,GAAG,CAAC,eAAe,EAAE,QAAQ,IAAI,aAAa,EAAE,SAAS,CAAC;SACpE,MAAM,CAAC,OAAO,CAAC;SACf,IAAI,CAAC,GAAG,CAAC,CAAC;IAEb,MAAM,WAAW,GAAG,CAAC,CAAsC,EAAE,EAAE;QAC7D,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,WAAW,EAAE,EAAE,CAAC;YAChB,GAAG,CAAC,KAAK,EAAE,CAAC;YACZ,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC;QACf,CAAC;IACH,CAAC,CAAC;IAEF,OAAO,CACL,iBACE,SAAS,EAAE,OAAO,EAClB,IAAI,EAAC,UAAU,EACf,QAAQ,EAAE,QAAQ,EAClB,OAAO,EAAE,WAAW,KAChB,IAAI,YAEP,QAAQ,GACF,CACV,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB;IAC9B,OAAO,aAAI,SAAS,EAAC,oBAAoB,GAAG,CAAC;AAC/C,CAAC;AAmBD;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAuB;IACpE,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IACxC,MAAM,UAAU,GAAG,MAAM,CAAc,IAAI,CAAC,CAAC;IAC7C,MAAM,OAAO,GAAG,MAAM,CAAiB,IAAI,CAAC,CAAC;IAE7C,4EAA4E;IAC5E,8EAA8E;IAC9E,wEAAwE;IACxE,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,EAAE,GAAG,UAAU,CAAC,OAAO,CAAC;QAC9B,IAAI,CAAC,EAAE;YAAE,OAAO;QAChB,EAAE,CAAC,YAAY,CAAC,eAAe,EAAE,MAAM,CAAC,CAAC;QACzC,EAAE,CAAC,YAAY,CAAC,eAAe,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;IACjD,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;IAEX,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,IAAI;YAAE,OAAO;QAElB,MAAM,kBAAkB,GAAG,CAAC,CAAa,EAAE,EAAE;YAC3C,IACE,CAAC,OAAO,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC,MAAc,CAAC;gBAC5C,CAAC,UAAU,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC,MAAc,CAAC,EAC/C,CAAC;gBACD,OAAO,CAAC,KAAK,CAAC,CAAC;YACjB,CAAC;QACH,CAAC,CAAC;QAEF,MAAM,aAAa,GAAG,CAAC,CAA2B,EAAE,EAAE;YACpD,IAAI,CAAC,CAAC,GAAG,KAAK,QAAQ;gBAAE,OAAO,CAAC,KAAK,CAAC,CAAC;QACzC,CAAC,CAAC;QAEF,QAAQ,CAAC,gBAAgB,CAAC,WAAW,EAAE,kBAAkB,CAAC,CAAC;QAC3D,QAAQ,CAAC,gBAAgB,CAAC,SAAS,EAAE,aAAa,CAAC,CAAC;QACpD,OAAO,GAAG,EAAE;YACV,QAAQ,CAAC,mBAAmB,CAAC,WAAW,EAAE,kBAAkB,CAAC,CAAC;YAC9D,QAAQ,CAAC,mBAAmB,CAAC,SAAS,EAAE,aAAa,CAAC,CAAC;QACzD,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;IAEX,OAAO,CACL,KAAC,WAAW,CAAC,QAAQ,IAAC,KAAK,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,YAC1D,eACE,SAAS,EAAC,0BAA0B,EACpC,KAAK,EAAE,EAAE,QAAQ,EAAE,UAAU,EAAE,OAAO,EAAE,cAAc,EAAE,aAEvD,QAAQ,CAAC,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,UAAU,EAAE,CAAC,EAChE,IAAI,IAAI,CACP,cAAK,GAAG,EAAE,OAAO,EAAE,SAAS,EAAC,gBAAgB,YAC1C,IAAI,GACD,CACP,IACG,GACe,CACxB,CAAC;AACJ,CAAC","sourcesContent":["import {\n createContext,\n useContext,\n useRef,\n useState,\n useEffect,\n ReactNode,\n HTMLAttributes,\n RefObject,\n} from 'react';\nimport type {\n AtlMenuSpec,\n AtlMenuItemSpec,\n} from '../spec';\nimport './atl-menu.css';\n\ninterface MenuContextValue {\n close: () => void;\n}\n\nconst MenuContext = createContext<MenuContextValue>({ close: () => undefined });\n\n/**\n * Properties for the AtlMenu component.\n */\nexport interface AtlMenuProps extends HTMLAttributes<HTMLDivElement>, AtlMenuSpec {\n /**\n * The visual style variant of the menu.\n */\n variant?: 'default' | 'compact';\n /**\n * The menu items to be rendered.\n */\n children?: ReactNode;\n}\n\n/**\n * A menu component for displaying a list of choices.\n */\nexport function AtlMenu({ variant = 'default', children, className, ...rest }: AtlMenuProps) {\n const classes = ['atl-menu', `variant-${variant}`, className].filter(Boolean).join(' ');\n return (\n <div className={classes} role=\"menu\" {...rest}>\n {children}\n </div>\n );\n}\n\n/**\n * Properties for the AtlMenuItem component.\n */\nexport interface AtlMenuItemProps\n extends HTMLAttributes<HTMLButtonElement>,\n AtlMenuItemSpec {\n /**\n * Whether the menu item is disabled.\n */\n disabled?: boolean;\n /**\n * Callback triggered when the item is selected.\n */\n onTriggered?: () => void;\n /**\n * The content of the menu item.\n */\n children?: ReactNode;\n}\n\n/**\n * An individual item within a menu.\n */\nexport function AtlMenuItem({\n disabled = false,\n onTriggered,\n children,\n className,\n onClick,\n ...rest\n}: AtlMenuItemProps) {\n const ctx = useContext(MenuContext);\n const classes = ['atl-menu-item', disabled && 'is-disabled', className]\n .filter(Boolean)\n .join(' ');\n\n const handleClick = (e: React.MouseEvent<HTMLButtonElement>) => {\n if (!disabled) {\n onTriggered?.();\n ctx.close();\n onClick?.(e);\n }\n };\n\n return (\n <button\n className={classes}\n role=\"menuitem\"\n disabled={disabled}\n onClick={handleClick}\n {...rest}\n >\n {children}\n </button>\n );\n}\n\n/**\n * A separator for dividing groups of menu items.\n */\nexport function AtlMenuSeparator() {\n return <hr className=\"atl-menu-separator\" />;\n}\n\n/**\n * Properties for the AtlMenuTrigger component.\n */\nexport interface AtlMenuTriggerProps {\n /**\n * The menu to be displayed.\n */\n menu: ReactNode;\n /**\n * Render prop that provides trigger functionality.\n */\n children: (props: {\n onClick: () => void;\n ref: RefObject<HTMLElement | null>;\n }) => ReactNode;\n}\n\n/**\n * A component that manages the state of a menu and its trigger.\n */\nexport function AtlMenuTrigger({ menu, children }: AtlMenuTriggerProps) {\n const [open, setOpen] = useState(false);\n const triggerRef = useRef<HTMLElement>(null);\n const menuRef = useRef<HTMLDivElement>(null);\n\n // Menu-button ARIA on the trigger element itself (the render prop binds the\n // ref to it) — mirrors what the CDK menu trigger does in the Angular adapter,\n // so consumers get correct semantics without wiring attributes by hand.\n useEffect(() => {\n const el = triggerRef.current;\n if (!el) return;\n el.setAttribute('aria-haspopup', 'menu');\n el.setAttribute('aria-expanded', String(open));\n }, [open]);\n\n useEffect(() => {\n if (!open) return;\n\n const handleOutsideClick = (e: MouseEvent) => {\n if (\n !menuRef.current?.contains(e.target as Node) &&\n !triggerRef.current?.contains(e.target as Node)\n ) {\n setOpen(false);\n }\n };\n\n const handleKeyDown = (e: globalThis.KeyboardEvent) => {\n if (e.key === 'Escape') setOpen(false);\n };\n\n document.addEventListener('mousedown', handleOutsideClick);\n document.addEventListener('keydown', handleKeyDown);\n return () => {\n document.removeEventListener('mousedown', handleOutsideClick);\n document.removeEventListener('keydown', handleKeyDown);\n };\n }, [open]);\n\n return (\n <MenuContext.Provider value={{ close: () => setOpen(false) }}>\n <div\n className=\"atl-menu-trigger-wrapper\"\n style={{ position: 'relative', display: 'inline-block' }}\n >\n {children({ onClick: () => setOpen((v) => !v), ref: triggerRef })}\n {open && (\n <div ref={menuRef} className=\"atl-menu-panel\">\n {menu}\n </div>\n )}\n </div>\n </MenuContext.Provider>\n );\n}\n"]}
|