@chayns-ui/layout 0.4.0 → 0.6.0

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 (30) hide show
  1. package/README.md +4 -2
  2. package/dist/app-layout.css +10 -1
  3. package/dist/components/app-layout/AppLayout.d.ts +12 -2
  4. package/dist/components/app-layout/AppLayout.d.ts.map +1 -1
  5. package/dist/components/app-layout/AppLayout.js +137 -67
  6. package/dist/components/app-layout/AppLayout.js.map +1 -1
  7. package/dist/components/app-layout/AppLayout.types.d.ts +16 -96
  8. package/dist/components/app-layout/AppLayout.types.d.ts.map +1 -1
  9. package/dist/components/app-layout/app-layout-icon/AppLayoutIcon.d.ts +2 -2
  10. package/dist/components/app-layout/app-layout-icon/AppLayoutIcon.d.ts.map +1 -1
  11. package/dist/components/tabs/Tabs.d.ts +7 -2
  12. package/dist/components/tabs/Tabs.d.ts.map +1 -1
  13. package/dist/components/tabs/Tabs.js +117 -91
  14. package/dist/components/tabs/Tabs.js.map +1 -1
  15. package/dist/components/tabs/Tabs.types.d.ts +14 -64
  16. package/dist/components/tabs/Tabs.types.d.ts.map +1 -1
  17. package/dist/components/tabs/tabs-icon/TabsIcon.d.ts +2 -2
  18. package/dist/components/tabs/tabs-icon/TabsIcon.d.ts.map +1 -1
  19. package/dist/index.d.ts +2 -2
  20. package/dist/index.d.ts.map +1 -1
  21. package/dist/tabs.css +2 -1
  22. package/package.json +3 -3
  23. package/dist/components/app-layout/app-layout-icon/AppLayoutIcon.js +0 -17
  24. package/dist/components/app-layout/app-layout-icon/AppLayoutIcon.js.map +0 -1
  25. package/dist/components/app-layout/navigation-items/NavigationItems.d.ts +0 -13
  26. package/dist/components/app-layout/navigation-items/NavigationItems.d.ts.map +0 -1
  27. package/dist/components/app-layout/navigation-items/NavigationItems.js +0 -54
  28. package/dist/components/app-layout/navigation-items/NavigationItems.js.map +0 -1
  29. package/dist/components/tabs/tabs-icon/TabsIcon.js +0 -11
  30. package/dist/components/tabs/tabs-icon/TabsIcon.js.map +0 -1
package/README.md CHANGED
@@ -20,8 +20,10 @@ import '@chayns-ui/layout/styles.css';
20
20
  import { AppLayout } from '@chayns-ui/layout';
21
21
  ```
22
22
 
23
- `AppLayout` renders the application shell with a 64px header, recursive
24
- navigation, controlled or uncontrolled sidebar collapse, and consumer content.
23
+ `AppLayout` wird über `Header`, `Logo`, `Navigation`, rekursive
24
+ `Navigation.Item`, `Content` und `CollapseToggle` komponiert. Der frühere
25
+ `items[]`-Vertrag wurde vor 1.0 entfernt. Tabs verwendet `Tabs.List`,
26
+ `Tabs.Tab value` und `Tabs.Panel value` statt `tabs[]`.
25
27
 
26
28
  Alternatively, the component stylesheet is available as
27
29
  `@chayns-ui/layout/app-layout.css` or
@@ -18,6 +18,15 @@
18
18
  padding-inline: var(--sp-4);
19
19
  }
20
20
 
21
+ .chayns-app-layout__header-content {
22
+ display: flex;
23
+ flex: 1 1 auto;
24
+ align-items: center;
25
+ justify-content: flex-end;
26
+ min-inline-size: 0;
27
+ margin-inline-start: var(--sp-4);
28
+ }
29
+
21
30
  .chayns-app-layout__logo {
22
31
  display: block;
23
32
  max-block-size: calc(var(--k32) + var(--k8));
@@ -30,7 +39,7 @@
30
39
  flex-direction: column;
31
40
  min-inline-size: 0;
32
41
  min-block-size: 0;
33
- padding: var(--sp-2);
42
+ padding: 0 var(--sp-2) var(--sp-2);
34
43
  }
35
44
 
36
45
  .chayns-app-layout__navigation {
@@ -1,3 +1,13 @@
1
- import type { AppLayoutProps } from './AppLayout.types.js';
2
- export declare const AppLayout: import("react").ForwardRefExoticComponent<Omit<AppLayoutProps, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
1
+ import type { AppLayoutCollapseToggleProps, AppLayoutNavigationItemProps, AppLayoutProps } from './AppLayout.types.js';
2
+ declare function NavigationItem({ children, className, href, isActive, label, ...props }: AppLayoutNavigationItemProps): import("react").JSX.Element;
3
+ export declare const AppLayout: import("react").ForwardRefExoticComponent<Omit<AppLayoutProps, "ref"> & import("react").RefAttributes<HTMLDivElement>> & {
4
+ CollapseToggle: import("react").ForwardRefExoticComponent<Omit<AppLayoutCollapseToggleProps, "ref"> & import("react").RefAttributes<HTMLButtonElement>>;
5
+ Content: import("react").ForwardRefExoticComponent<Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLElement>, HTMLElement>, "ref"> & import("react").RefAttributes<HTMLElement>>;
6
+ Header: import("react").ForwardRefExoticComponent<Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLElement>, HTMLElement>, "ref"> & import("react").RefAttributes<HTMLElement>>;
7
+ Logo: import("react").ForwardRefExoticComponent<Omit<import("react").DetailedHTMLProps<import("react").ImgHTMLAttributes<HTMLImageElement>, HTMLImageElement>, "ref"> & import("react").RefAttributes<HTMLImageElement>>;
8
+ Navigation: import("react").ForwardRefExoticComponent<Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLElement>, HTMLElement>, "ref"> & import("react").RefAttributes<HTMLElement>> & {
9
+ Item: typeof NavigationItem;
10
+ };
11
+ };
12
+ export {};
3
13
  //# sourceMappingURL=AppLayout.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"AppLayout.d.ts","sourceRoot":"","sources":["../../../src/components/app-layout/AppLayout.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAI3D,eAAO,MAAM,SAAS,wHAmFrB,CAAC"}
1
+ {"version":3,"file":"AppLayout.d.ts","sourceRoot":"","sources":["../../../src/components/app-layout/AppLayout.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,4BAA4B,EAI5B,4BAA4B,EAE5B,cAAc,EACf,MAAM,sBAAsB,CAAC;AA4D9B,iBAAS,cAAc,CAAC,EACtB,QAAQ,EACR,SAAS,EACT,IAAI,EACJ,QAAgB,EAChB,KAAK,EACL,GAAG,KAAK,EACT,EAAE,4BAA4B,+BA2D9B;AAgED,eAAO,MAAM,SAAS;;;;;;;;CAMpB,CAAC"}
@@ -1,77 +1,147 @@
1
- import AppLayoutIcon from "./app-layout-icon/AppLayoutIcon.js";
2
- import NavigationItems from "./navigation-items/NavigationItems.js";
3
- import { forwardRef, useId, useState } from "react";
1
+ import { createContext, forwardRef, useContext, useState } from "react";
4
2
  import { jsx, jsxs } from "react/jsx-runtime";
5
3
  //#region src/components/app-layout/AppLayout.tsx
6
- var AppLayout = forwardRef(({ activeItemId, children, className, collapseLabel, collapsed, defaultCollapsed = false, expandLabel, items, logo, navigationLabel, onClick, onCollapsedChange, ...rootProps }, ref) => {
7
- const baseId = useId();
8
- const [internalCollapsed, setInternalCollapsed] = useState(defaultCollapsed);
9
- const [expandedIds, setExpandedIds] = useState(() => /* @__PURE__ */ new Set());
10
- const isCollapsed = collapsed ?? internalCollapsed;
11
- const rootClassName = [
12
- "chayns-app-layout",
13
- isCollapsed ? "chayns-app-layout--collapsed" : void 0,
14
- className
15
- ].filter(Boolean).join(" ");
16
- const handleCollapsedChange = () => {
17
- const nextCollapsed = !isCollapsed;
18
- if (collapsed === void 0) setInternalCollapsed(nextCollapsed);
19
- onCollapsedChange?.(nextCollapsed);
20
- };
21
- const handleToggle = (id) => {
22
- setExpandedIds((current) => {
23
- const next = new Set(current);
24
- if (next.has(id)) next.delete(id);
25
- else next.add(id);
26
- return next;
27
- });
28
- };
29
- return /* @__PURE__ */ jsxs("div", {
30
- ...rootProps,
31
- className: rootClassName,
4
+ var LayoutContext = createContext(null);
5
+ var NavigationContext = createContext(false);
6
+ function useLayout(part) {
7
+ const context = useContext(LayoutContext);
8
+ if (context === null) throw new Error(`AppLayout.${part} must be rendered within AppLayout.`);
9
+ return context;
10
+ }
11
+ var Header = forwardRef(function Header({ children, className, ...props }, ref) {
12
+ useLayout("Header");
13
+ return /* @__PURE__ */ jsx("header", {
14
+ ...props,
15
+ className: ["chayns-app-layout__header", className].filter(Boolean).join(" "),
32
16
  ref,
33
- children: [
34
- /* @__PURE__ */ jsx("header", {
35
- className: "chayns-app-layout__header",
36
- children: /* @__PURE__ */ jsx("img", {
37
- alt: "",
38
- className: "chayns-app-layout__logo",
39
- src: logo
40
- })
41
- }),
42
- /* @__PURE__ */ jsxs("aside", {
43
- className: "chayns-app-layout__sidebar",
44
- children: [/* @__PURE__ */ jsx("nav", {
45
- "aria-label": navigationLabel,
46
- className: "chayns-app-layout__navigation",
47
- children: /* @__PURE__ */ jsx(NavigationItems, {
48
- activeItemId,
49
- collapsed: isCollapsed,
50
- expandedIds,
51
- items,
52
- onClick,
53
- onToggle: handleToggle,
54
- parentId: baseId
55
- })
56
- }), /* @__PURE__ */ jsx("div", {
57
- className: "chayns-app-layout__footer",
58
- children: /* @__PURE__ */ jsx("button", {
59
- "aria-label": isCollapsed ? expandLabel : collapseLabel,
60
- className: "chayns-app-layout__collapse",
61
- onClick: handleCollapsedChange,
62
- type: "button",
63
- children: /* @__PURE__ */ jsx(AppLayoutIcon, { icon: "fa-sidebar" })
64
- })
65
- })]
66
- }),
67
- /* @__PURE__ */ jsx("main", {
68
- className: "chayns-app-layout__content",
17
+ children
18
+ });
19
+ });
20
+ var Logo = forwardRef(function Logo({ alt = "", className, ...props }, ref) {
21
+ useLayout("Logo");
22
+ return /* @__PURE__ */ jsx("img", {
23
+ ...props,
24
+ alt,
25
+ className: ["chayns-app-layout__logo", className].filter(Boolean).join(" "),
26
+ ref
27
+ });
28
+ });
29
+ var Navigation = forwardRef(function Navigation({ children, className, ...props }, ref) {
30
+ useLayout("Navigation");
31
+ return /* @__PURE__ */ jsx(NavigationContext.Provider, {
32
+ value: true,
33
+ children: /* @__PURE__ */ jsx("nav", {
34
+ ...props,
35
+ className: ["chayns-app-layout__navigation", className].filter(Boolean).join(" "),
36
+ ref,
37
+ children: /* @__PURE__ */ jsx("ul", {
38
+ className: "chayns-app-layout__list",
39
+ children
40
+ })
41
+ })
42
+ });
43
+ });
44
+ function NavigationItem({ children, className, href, isActive = false, label, ...props }) {
45
+ if (!useContext(NavigationContext)) throw new Error("AppLayout.Navigation.Item must be rendered within AppLayout.Navigation.");
46
+ const { collapsed } = useLayout("Navigation.Item");
47
+ const [expanded, setExpanded] = useState(false);
48
+ const hasChildren = children !== void 0;
49
+ const content = /* @__PURE__ */ jsx("span", {
50
+ className: `chayns-app-layout__label${collapsed ? " chayns-app-layout__label--hidden" : ""}`,
51
+ children: label
52
+ });
53
+ const actionClass = ["chayns-app-layout__action", className].filter(Boolean).join(" ");
54
+ return /* @__PURE__ */ jsxs("li", {
55
+ className: `chayns-app-layout__item${isActive ? " chayns-app-layout__item--active" : ""}`,
56
+ children: [/* @__PURE__ */ jsxs("div", {
57
+ className: "chayns-app-layout__row",
58
+ children: [href ? /* @__PURE__ */ jsx("a", {
59
+ ...props,
60
+ "aria-current": isActive ? "page" : void 0,
61
+ className: actionClass,
62
+ href,
63
+ children: content
64
+ }) : /* @__PURE__ */ jsx("button", {
65
+ ...props,
66
+ "aria-current": isActive ? "page" : void 0,
67
+ className: actionClass,
68
+ type: "button",
69
+ children: content
70
+ }), hasChildren && !collapsed ? /* @__PURE__ */ jsx("button", {
71
+ "aria-label": typeof label === "string" ? label : void 0,
72
+ "aria-expanded": expanded,
73
+ className: "chayns-app-layout__disclosure",
74
+ onClick: () => setExpanded((current) => !current),
75
+ type: "button",
76
+ children: "⌄"
77
+ }) : null]
78
+ }), hasChildren && !collapsed ? /* @__PURE__ */ jsx("div", {
79
+ "aria-hidden": !expanded,
80
+ className: `chayns-app-layout__children${expanded ? " chayns-app-layout__children--open" : ""}`,
81
+ inert: !expanded,
82
+ children: /* @__PURE__ */ jsx("ul", {
83
+ className: "chayns-app-layout__list",
69
84
  children
70
85
  })
71
- ]
86
+ }) : null]
87
+ });
88
+ }
89
+ var Content = forwardRef(function Content({ children, className, ...props }, ref) {
90
+ useLayout("Content");
91
+ return /* @__PURE__ */ jsx("main", {
92
+ ...props,
93
+ className: ["chayns-app-layout__content", className].filter(Boolean).join(" "),
94
+ ref,
95
+ children
96
+ });
97
+ });
98
+ var CollapseToggle = forwardRef(function CollapseToggle({ children = "☰", className, collapseLabel, expandLabel, onClick, ...props }, ref) {
99
+ const layout = useLayout("CollapseToggle");
100
+ return /* @__PURE__ */ jsx("button", {
101
+ ...props,
102
+ "aria-label": layout.collapsed ? expandLabel : collapseLabel,
103
+ className: ["chayns-app-layout__collapse", className].filter(Boolean).join(" "),
104
+ onClick: (event) => {
105
+ onClick?.(event);
106
+ if (!event.defaultPrevented) layout.toggle();
107
+ },
108
+ ref,
109
+ type: "button",
110
+ children
72
111
  });
73
112
  });
74
- AppLayout.displayName = "AppLayout";
113
+ var Root = forwardRef(function Root({ children, className, collapsed, defaultCollapsed = false, onCollapsedChange, ...props }, ref) {
114
+ const [internal, setInternal] = useState(defaultCollapsed);
115
+ const isCollapsed = collapsed ?? internal;
116
+ const toggle = () => {
117
+ const next = !isCollapsed;
118
+ if (collapsed === void 0) setInternal(next);
119
+ onCollapsedChange?.(next);
120
+ };
121
+ return /* @__PURE__ */ jsx(LayoutContext.Provider, {
122
+ value: {
123
+ collapsed: isCollapsed,
124
+ toggle
125
+ },
126
+ children: /* @__PURE__ */ jsx("div", {
127
+ ...props,
128
+ className: [
129
+ "chayns-app-layout",
130
+ isCollapsed && "chayns-app-layout--collapsed",
131
+ className
132
+ ].filter(Boolean).join(" "),
133
+ ref,
134
+ children
135
+ })
136
+ });
137
+ });
138
+ var AppLayout = Object.assign(Root, {
139
+ CollapseToggle,
140
+ Content,
141
+ Header,
142
+ Logo,
143
+ Navigation: Object.assign(Navigation, { Item: NavigationItem })
144
+ });
75
145
  //#endregion
76
146
  export { AppLayout };
77
147
 
@@ -1 +1 @@
1
- {"version":3,"file":"AppLayout.js","names":[],"sources":["../../../src/components/app-layout/AppLayout.tsx"],"sourcesContent":["import { forwardRef, useId, useState } from 'react';\n\nimport type { AppLayoutProps } from './AppLayout.types.js';\nimport AppLayoutIcon from './app-layout-icon/AppLayoutIcon.js';\nimport NavigationItems from './navigation-items/NavigationItems.js';\n\nexport const AppLayout = forwardRef<HTMLDivElement, AppLayoutProps>(\n (\n {\n activeItemId,\n children,\n className,\n collapseLabel,\n collapsed,\n defaultCollapsed = false,\n expandLabel,\n items,\n logo,\n navigationLabel,\n onClick,\n onCollapsedChange,\n ...rootProps\n },\n ref,\n ) => {\n const baseId = useId();\n const [internalCollapsed, setInternalCollapsed] = useState(defaultCollapsed);\n const [expandedIds, setExpandedIds] = useState<ReadonlySet<string>>(() => new Set());\n const isCollapsed = collapsed ?? internalCollapsed;\n const rootClassName = [\n 'chayns-app-layout',\n isCollapsed ? 'chayns-app-layout--collapsed' : undefined,\n className,\n ]\n .filter(Boolean)\n .join(' ');\n\n const handleCollapsedChange = () => {\n const nextCollapsed = !isCollapsed;\n if (collapsed === undefined) {\n setInternalCollapsed(nextCollapsed);\n }\n onCollapsedChange?.(nextCollapsed);\n };\n\n const handleToggle = (id: string) => {\n setExpandedIds((current) => {\n const next = new Set(current);\n if (next.has(id)) {\n next.delete(id);\n } else {\n next.add(id);\n }\n return next;\n });\n };\n\n return (\n <div {...rootProps} className={rootClassName} ref={ref}>\n <header className=\"chayns-app-layout__header\">\n <img alt=\"\" className=\"chayns-app-layout__logo\" src={logo} />\n </header>\n <aside className=\"chayns-app-layout__sidebar\">\n <nav aria-label={navigationLabel} className=\"chayns-app-layout__navigation\">\n <NavigationItems\n activeItemId={activeItemId}\n collapsed={isCollapsed}\n expandedIds={expandedIds}\n items={items}\n onClick={onClick}\n onToggle={handleToggle}\n parentId={baseId}\n />\n </nav>\n <div className=\"chayns-app-layout__footer\">\n <button\n aria-label={isCollapsed ? expandLabel : collapseLabel}\n className=\"chayns-app-layout__collapse\"\n onClick={handleCollapsedChange}\n type=\"button\"\n >\n <AppLayoutIcon icon=\"fa-sidebar\" />\n </button>\n </div>\n </aside>\n <main className=\"chayns-app-layout__content\">{children}</main>\n </div>\n );\n },\n);\n\nAppLayout.displayName = 'AppLayout';\n"],"mappings":";;;;;AAMA,IAAa,YAAY,YAErB,EACE,cACA,UACA,WACA,eACA,WACA,mBAAmB,OACnB,aACA,OACA,MACA,iBACA,SACA,mBACA,GAAG,aAEL,QACG;CACH,MAAM,SAAS,MAAM;CACrB,MAAM,CAAC,mBAAmB,wBAAwB,SAAS,gBAAgB;CAC3E,MAAM,CAAC,aAAa,kBAAkB,+BAAoC,IAAI,IAAI,CAAC;CACnF,MAAM,cAAc,aAAa;CACjC,MAAM,gBAAgB;EACpB;EACA,cAAc,iCAAiC,KAAA;EAC/C;CACF,CAAC,CACE,OAAO,OAAO,CAAC,CACf,KAAK,GAAG;CAEX,MAAM,8BAA8B;EAClC,MAAM,gBAAgB,CAAC;EACvB,IAAI,cAAc,KAAA,GAChB,qBAAqB,aAAa;EAEpC,oBAAoB,aAAa;CACnC;CAEA,MAAM,gBAAgB,OAAe;EACnC,gBAAgB,YAAY;GAC1B,MAAM,OAAO,IAAI,IAAI,OAAO;GAC5B,IAAI,KAAK,IAAI,EAAE,GACb,KAAK,OAAO,EAAE;QAEd,KAAK,IAAI,EAAE;GAEb,OAAO;EACT,CAAC;CACH;CAEA,OACE,qBAAC,OAAD;EAAK,GAAI;EAAW,WAAW;EAAoB;EAAnD,UAAA;GACE,oBAAC,UAAD;IAAQ,WAAU;IAChB,UAAA,oBAAC,OAAD;KAAK,KAAI;KAAG,WAAU;KAA0B,KAAK;IAAO,CAAA;GACtD,CAAA;GACR,qBAAC,SAAD;IAAO,WAAU;IAAjB,UAAA,CACE,oBAAC,OAAD;KAAK,cAAY;KAAiB,WAAU;KAC1C,UAAA,oBAAC,iBAAD;MACgB;MACd,WAAW;MACE;MACN;MACE;MACT,UAAU;MACV,UAAU;KACX,CAAA;IACE,CAAA,GACL,oBAAC,OAAD;KAAK,WAAU;KACb,UAAA,oBAAC,UAAD;MACE,cAAY,cAAc,cAAc;MACxC,WAAU;MACV,SAAS;MACT,MAAK;MAEL,UAAA,oBAAC,eAAD,EAAe,MAAK,aAAc,CAAA;KAC5B,CAAA;IACL,CAAA,CACA;;GACP,oBAAC,QAAD;IAAM,WAAU;IAA8B;GAAe,CAAA;EAC1D;;AAET,CACF;AAEA,UAAU,cAAc"}
1
+ {"version":3,"file":"AppLayout.js","names":[],"sources":["../../../src/components/app-layout/AppLayout.tsx"],"sourcesContent":["import { createContext, forwardRef, useContext, useState } from 'react';\nimport type { ComponentPropsWithRef } from 'react';\nimport type {\n AppLayoutCollapseToggleProps,\n AppLayoutContentProps,\n AppLayoutHeaderProps,\n AppLayoutLogoProps,\n AppLayoutNavigationItemProps,\n AppLayoutNavigationProps,\n AppLayoutProps,\n} from './AppLayout.types.js';\n\ninterface LayoutState {\n collapsed: boolean;\n toggle: () => void;\n}\nconst LayoutContext = createContext<LayoutState | null>(null);\nconst NavigationContext = createContext(false);\nfunction useLayout(part: string) {\n const context = useContext(LayoutContext);\n if (context === null) throw new Error(`AppLayout.${part} must be rendered within AppLayout.`);\n return context;\n}\n\nconst Header = forwardRef<HTMLElement, AppLayoutHeaderProps>(function Header(\n { children, className, ...props },\n ref,\n) {\n useLayout('Header');\n return (\n <header\n {...props}\n className={['chayns-app-layout__header', className].filter(Boolean).join(' ')}\n ref={ref}\n >\n {children}\n </header>\n );\n});\nconst Logo = forwardRef<HTMLImageElement, AppLayoutLogoProps>(function Logo(\n { alt = '', className, ...props },\n ref,\n) {\n useLayout('Logo');\n return (\n <img\n {...props}\n alt={alt}\n className={['chayns-app-layout__logo', className].filter(Boolean).join(' ')}\n ref={ref}\n />\n );\n});\nconst Navigation = forwardRef<HTMLElement, AppLayoutNavigationProps>(function Navigation(\n { children, className, ...props },\n ref,\n) {\n useLayout('Navigation');\n return (\n <NavigationContext.Provider value>\n <nav\n {...props}\n className={['chayns-app-layout__navigation', className].filter(Boolean).join(' ')}\n ref={ref}\n >\n <ul className=\"chayns-app-layout__list\">{children}</ul>\n </nav>\n </NavigationContext.Provider>\n );\n});\nfunction NavigationItem({\n children,\n className,\n href,\n isActive = false,\n label,\n ...props\n}: AppLayoutNavigationItemProps) {\n if (!useContext(NavigationContext))\n throw new Error('AppLayout.Navigation.Item must be rendered within AppLayout.Navigation.');\n const { collapsed } = useLayout('Navigation.Item');\n const [expanded, setExpanded] = useState(false);\n const hasChildren = children !== undefined;\n const content = (\n <span\n className={`chayns-app-layout__label${collapsed ? ' chayns-app-layout__label--hidden' : ''}`}\n >\n {label}\n </span>\n );\n const actionClass = ['chayns-app-layout__action', className].filter(Boolean).join(' ');\n return (\n <li className={`chayns-app-layout__item${isActive ? ' chayns-app-layout__item--active' : ''}`}>\n <div className=\"chayns-app-layout__row\">\n {href ? (\n <a\n {...(props as ComponentPropsWithRef<'a'>)}\n aria-current={isActive ? 'page' : undefined}\n className={actionClass}\n href={href}\n >\n {content}\n </a>\n ) : (\n <button\n {...props}\n aria-current={isActive ? 'page' : undefined}\n className={actionClass}\n type=\"button\"\n >\n {content}\n </button>\n )}\n {hasChildren && !collapsed ? (\n <button\n aria-label={typeof label === 'string' ? label : undefined}\n aria-expanded={expanded}\n className=\"chayns-app-layout__disclosure\"\n onClick={() => setExpanded((current) => !current)}\n type=\"button\"\n >\n ⌄\n </button>\n ) : null}\n </div>\n {hasChildren && !collapsed ? (\n <div\n aria-hidden={!expanded}\n className={`chayns-app-layout__children${expanded ? ' chayns-app-layout__children--open' : ''}`}\n inert={!expanded}\n >\n <ul className=\"chayns-app-layout__list\">{children}</ul>\n </div>\n ) : null}\n </li>\n );\n}\nconst Content = forwardRef<HTMLElement, AppLayoutContentProps>(function Content(\n { children, className, ...props },\n ref,\n) {\n useLayout('Content');\n return (\n <main\n {...props}\n className={['chayns-app-layout__content', className].filter(Boolean).join(' ')}\n ref={ref}\n >\n {children}\n </main>\n );\n});\nconst CollapseToggle = forwardRef<HTMLButtonElement, AppLayoutCollapseToggleProps>(\n function CollapseToggle(\n { children = '☰', className, collapseLabel, expandLabel, onClick, ...props },\n ref,\n ) {\n const layout = useLayout('CollapseToggle');\n return (\n <button\n {...props}\n aria-label={layout.collapsed ? expandLabel : collapseLabel}\n className={['chayns-app-layout__collapse', className].filter(Boolean).join(' ')}\n onClick={(event) => {\n onClick?.(event);\n if (!event.defaultPrevented) layout.toggle();\n }}\n ref={ref}\n type=\"button\"\n >\n {children}\n </button>\n );\n },\n);\nconst Root = forwardRef<HTMLDivElement, AppLayoutProps>(function Root(\n { children, className, collapsed, defaultCollapsed = false, onCollapsedChange, ...props },\n ref,\n) {\n const [internal, setInternal] = useState(defaultCollapsed);\n const isCollapsed = collapsed ?? internal;\n const toggle = () => {\n const next = !isCollapsed;\n if (collapsed === undefined) setInternal(next);\n onCollapsedChange?.(next);\n };\n return (\n <LayoutContext.Provider value={{ collapsed: isCollapsed, toggle }}>\n <div\n {...props}\n className={['chayns-app-layout', isCollapsed && 'chayns-app-layout--collapsed', className]\n .filter(Boolean)\n .join(' ')}\n ref={ref}\n >\n {children}\n </div>\n </LayoutContext.Provider>\n );\n});\nexport const AppLayout = Object.assign(Root, {\n CollapseToggle,\n Content,\n Header,\n Logo,\n Navigation: Object.assign(Navigation, { Item: NavigationItem }),\n});\n"],"mappings":"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"}
@@ -1,103 +1,23 @@
1
1
  import type { ComponentPropsWithRef, ReactNode } from 'react';
2
- /**
3
- * @description A FontAwesome Classic icon name in its Regular form, used for
4
- * navigation item icons in `AppLayout`.
5
- */
6
- export type AppLayoutIcon = `fa-${string}`;
7
- /**
8
- * @description A single, recursively composable navigation entry in the
9
- * `AppLayout` sidebar. Parent and child items each act as their own action
10
- * button; a parent item with `children` additionally exposes a separate
11
- * disclosure control, so activating the parent's own action and toggling its
12
- * nested children are independent.
13
- */
14
- export interface AppLayoutItem {
15
- /**
16
- * @description Stable identifier passed to `onClick` and compared against
17
- * `activeItemId`.
18
- */
19
- id: string;
20
- /**
21
- * @description Visible, localized navigation label. Remains accessible for
22
- * each item even while the sidebar is collapsed.
23
- */
24
- name: string;
25
- /**
26
- * @description FontAwesome Classic icon name shown for this item, including
27
- * in the collapsed sidebar.
28
- */
29
- icon: AppLayoutIcon;
30
- /**
31
- * @description Nested child items, rendered behind this item's own
32
- * disclosure control and hidden while the sidebar is collapsed.
33
- */
34
- children?: AppLayoutItem[];
2
+ export interface AppLayoutProps extends Omit<ComponentPropsWithRef<'div'>, 'children'> {
3
+ children: ReactNode;
4
+ collapsed?: boolean;
5
+ defaultCollapsed?: boolean;
6
+ onCollapsedChange?: (collapsed: boolean) => void;
7
+ }
8
+ export type AppLayoutHeaderProps = ComponentPropsWithRef<'header'>;
9
+ export type AppLayoutLogoProps = ComponentPropsWithRef<'img'>;
10
+ export type AppLayoutNavigationProps = ComponentPropsWithRef<'nav'>;
11
+ export interface AppLayoutNavigationItemProps extends Omit<ComponentPropsWithRef<'button'>, 'children' | 'ref' | 'type'> {
12
+ label: ReactNode;
13
+ children?: ReactNode;
14
+ href?: string;
15
+ isActive?: boolean;
35
16
  }
36
- /**
37
- * @description Props for the top-level application shell: a header with a
38
- * logo, a collapsible sidebar of recursively nested navigation items, and a
39
- * consumer-owned content area. Forwards all remaining native `div` props
40
- * (except `children` and `onClick`, which have `AppLayout`-specific meaning),
41
- * `className` and `ref`.
42
- */
43
- export interface AppLayoutProps extends Omit<ComponentPropsWithRef<'div'>, 'children' | 'onClick'> {
44
- /**
45
- * @description URL of an image or SVG resource rendered as the header logo.
46
- * Always decorative (`alt=""`); it does not itself provide any accessible
47
- * name.
48
- */
49
- logo: string;
50
- /**
51
- * @description Top-level navigation items, recursively composable via each
52
- * item's own `children`. An empty array renders an empty navigation list.
53
- */
54
- items: AppLayoutItem[];
55
- /**
56
- * @description Called with an item's `id` when that item's own action is
57
- * activated, for both parent and child items. Toggling a parent's
58
- * disclosure control does not call `onClick`.
59
- */
60
- onClick: (id: string) => void;
61
- /**
62
- * @description Localized accessible name for the navigation landmark.
63
- */
64
- navigationLabel: string;
65
- /**
66
- * @description Localized accessible name for the sidebar toggle control
67
- * when activating it will collapse the sidebar.
68
- */
17
+ export type AppLayoutContentProps = ComponentPropsWithRef<'main'>;
18
+ export interface AppLayoutCollapseToggleProps extends Omit<ComponentPropsWithRef<'button'>, 'children' | 'type' | 'aria-label'> {
69
19
  collapseLabel: string;
70
- /**
71
- * @description Localized accessible name for the sidebar toggle control
72
- * when activating it will expand the sidebar.
73
- */
74
20
  expandLabel: string;
75
- /**
76
- * @description `id` of the currently active navigation item. `AppLayout`
77
- * only renders the active visual state; it does not derive or own
78
- * activeness from routing.
79
- */
80
- activeItemId?: string;
81
- /**
82
- * @description Consumer-provided content rendered in the area beside the
83
- * sidebar. Owns its own internal semantics and scrolling.
84
- */
85
21
  children?: ReactNode;
86
- /**
87
- * @description Controlled collapsed state of the sidebar.
88
- */
89
- collapsed?: boolean;
90
- /**
91
- * @description Uncontrolled initial collapsed state of the sidebar.
92
- * Persisting the collapsed state across sessions is outside `AppLayout`'s
93
- * responsibility.
94
- * @default false
95
- */
96
- defaultCollapsed?: boolean;
97
- /**
98
- * @description Called with the next collapsed state when the sidebar
99
- * toggle is activated, for both the controlled and uncontrolled usage.
100
- */
101
- onCollapsedChange?: (collapsed: boolean) => void;
102
22
  }
103
23
  //# sourceMappingURL=AppLayout.types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"AppLayout.types.d.ts","sourceRoot":"","sources":["../../../src/components/app-layout/AppLayout.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAE9D;;;GAGG;AACH,MAAM,MAAM,aAAa,GAAG,MAAM,MAAM,EAAE,CAAC;AAE3C;;;;;;GAMG;AACH,MAAM,WAAW,aAAa;IAC5B;;;OAGG;IACH,EAAE,EAAE,MAAM,CAAC;IAEX;;;OAGG;IACH,IAAI,EAAE,MAAM,CAAC;IAEb;;;OAGG;IACH,IAAI,EAAE,aAAa,CAAC;IAEpB;;;OAGG;IACH,QAAQ,CAAC,EAAE,aAAa,EAAE,CAAC;CAC5B;AAED;;;;;;GAMG;AACH,MAAM,WAAW,cAAe,SAAQ,IAAI,CAAC,qBAAqB,CAAC,KAAK,CAAC,EAAE,UAAU,GAAG,SAAS,CAAC;IAChG;;;;OAIG;IACH,IAAI,EAAE,MAAM,CAAC;IAEb;;;OAGG;IACH,KAAK,EAAE,aAAa,EAAE,CAAC;IAEvB;;;;OAIG;IACH,OAAO,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAE9B;;OAEG;IACH,eAAe,EAAE,MAAM,CAAC;IAExB;;;OAGG;IACH,aAAa,EAAE,MAAM,CAAC;IAEtB;;;OAGG;IACH,WAAW,EAAE,MAAM,CAAC;IAEpB;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB;;;OAGG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAC;IAErB;;OAEG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IAEpB;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAE3B;;;OAGG;IACH,iBAAiB,CAAC,EAAE,CAAC,SAAS,EAAE,OAAO,KAAK,IAAI,CAAC;CAClD"}
1
+ {"version":3,"file":"AppLayout.types.d.ts","sourceRoot":"","sources":["../../../src/components/app-layout/AppLayout.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAE9D,MAAM,WAAW,cAAe,SAAQ,IAAI,CAAC,qBAAqB,CAAC,KAAK,CAAC,EAAE,UAAU,CAAC;IACpF,QAAQ,EAAE,SAAS,CAAC;IACpB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,iBAAiB,CAAC,EAAE,CAAC,SAAS,EAAE,OAAO,KAAK,IAAI,CAAC;CAClD;AACD,MAAM,MAAM,oBAAoB,GAAG,qBAAqB,CAAC,QAAQ,CAAC,CAAC;AACnE,MAAM,MAAM,kBAAkB,GAAG,qBAAqB,CAAC,KAAK,CAAC,CAAC;AAC9D,MAAM,MAAM,wBAAwB,GAAG,qBAAqB,CAAC,KAAK,CAAC,CAAC;AACpE,MAAM,WAAW,4BAA6B,SAAQ,IAAI,CACxD,qBAAqB,CAAC,QAAQ,CAAC,EAC/B,UAAU,GAAG,KAAK,GAAG,MAAM,CAC5B;IACC,KAAK,EAAE,SAAS,CAAC;IACjB,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AACD,MAAM,MAAM,qBAAqB,GAAG,qBAAqB,CAAC,MAAM,CAAC,CAAC;AAClE,MAAM,WAAW,4BAA6B,SAAQ,IAAI,CACxD,qBAAqB,CAAC,QAAQ,CAAC,EAC/B,UAAU,GAAG,MAAM,GAAG,YAAY,CACnC;IACC,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB"}
@@ -1,6 +1,6 @@
1
- import type { AppLayoutItem } from '../AppLayout.types.js';
1
+ type AppLayoutIconName = `fa-${string}`;
2
2
  declare const AppLayoutIcon: ({ icon }: {
3
- icon: AppLayoutItem["icon"];
3
+ icon: AppLayoutIconName;
4
4
  }) => import("react").JSX.Element;
5
5
  export default AppLayoutIcon;
6
6
  //# sourceMappingURL=AppLayoutIcon.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"AppLayoutIcon.d.ts","sourceRoot":"","sources":["../../../../src/components/app-layout/app-layout-icon/AppLayoutIcon.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAE3D,QAAA,MAAM,aAAa,GAAI,UAAU;IAAE,IAAI,EAAE,aAAa,CAAC,MAAM,CAAC,CAAA;CAAE,gCAS/D,CAAC;AAEF,eAAe,aAAa,CAAC"}
1
+ {"version":3,"file":"AppLayoutIcon.d.ts","sourceRoot":"","sources":["../../../../src/components/app-layout/app-layout-icon/AppLayoutIcon.tsx"],"names":[],"mappings":"AAAA,KAAK,iBAAiB,GAAG,MAAM,MAAM,EAAE,CAAC;AAExC,QAAA,MAAM,aAAa,GAAI,UAAU;IAAE,IAAI,EAAE,iBAAiB,CAAA;CAAE,gCAS3D,CAAC;AAEF,eAAe,aAAa,CAAC"}
@@ -1,3 +1,8 @@
1
- import type { TabsProps } from './Tabs.types.js';
2
- export declare const Tabs: import("react").ForwardRefExoticComponent<Omit<TabsProps, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
1
+ import type { TabsPanelProps, TabsProps, TabsTabProps } from './Tabs.types.js';
2
+ export declare const Tabs: import("react").ForwardRefExoticComponent<Omit<TabsProps, "ref"> & import("react").RefAttributes<HTMLDivElement>> & {
3
+ Add: import("react").ForwardRefExoticComponent<Omit<import("react").DetailedHTMLProps<import("react").ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, "ref"> & import("react").RefAttributes<HTMLButtonElement>>;
4
+ List: import("react").ForwardRefExoticComponent<Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
5
+ Panel: import("react").ForwardRefExoticComponent<Omit<TabsPanelProps, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
6
+ Tab: import("react").ForwardRefExoticComponent<Omit<TabsTabProps, "ref"> & import("react").RefAttributes<HTMLButtonElement>>;
7
+ };
3
8
  //# sourceMappingURL=Tabs.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Tabs.d.ts","sourceRoot":"","sources":["../../../src/components/tabs/Tabs.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAGjD,eAAO,MAAM,IAAI,mHA6Gf,CAAC"}
1
+ {"version":3,"file":"Tabs.d.ts","sourceRoot":"","sources":["../../../src/components/tabs/Tabs.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAGV,cAAc,EACd,SAAS,EACT,YAAY,EACb,MAAM,iBAAiB,CAAC;AAuJzB,eAAO,MAAM,IAAI;;;;;CAAiD,CAAC"}
@@ -1,101 +1,127 @@
1
- import TabsIcon from "./tabs-icon/TabsIcon.js";
2
- import { forwardRef, useId, useRef } from "react";
3
- import { jsx, jsxs } from "react/jsx-runtime";
1
+ import { createContext, forwardRef, useContext, useId, useState } from "react";
2
+ import { jsx } from "react/jsx-runtime";
4
3
  //#region src/components/tabs/Tabs.tsx
5
- var Tabs = forwardRef(function Tabs({ addLabel, className, onAdd, tabs, ...rootProps }, ref) {
6
- const baseId = useId();
7
- const tabRefs = useRef([]);
8
- const activeIndex = Math.max(0, tabs.findIndex((tab) => tab.isActive));
9
- const rootClassName = ["chayns-tabs", className].filter(Boolean).join(" ");
10
- const focusTab = (index) => {
11
- const nextIndex = (index + tabs.length) % tabs.length;
12
- tabs[nextIndex]?.onClick();
13
- tabRefs.current[nextIndex]?.focus();
14
- };
15
- const handleKeyDown = (event, index) => {
16
- if ((event.key === "Delete" || event.key === "Backspace") && tabs[index]?.onRemove) {
4
+ var TabsContext = createContext(null);
5
+ function useTabs(part) {
6
+ const context = useContext(TabsContext);
7
+ if (context === null) throw new Error(`Tabs.${part} must be rendered within Tabs.`);
8
+ return context;
9
+ }
10
+ var List = forwardRef(function List({ children, className, ...props }, ref) {
11
+ useTabs("List");
12
+ return /* @__PURE__ */ jsx("div", {
13
+ ...props,
14
+ className: ["chayns-tabs__list", className].filter(Boolean).join(" "),
15
+ ref,
16
+ role: "tablist",
17
+ children
18
+ });
19
+ });
20
+ var Tab = forwardRef(function Tab({ children, className, onRemove, onClick, value, ...props }, ref) {
21
+ const tabs = useTabs("Tab");
22
+ const selected = tabs.value === value;
23
+ const tabId = `${tabs.baseId}-tab-${value}`;
24
+ const panelId = `${tabs.baseId}-panel-${value}`;
25
+ function handleKeyDown(event) {
26
+ if ((event.key === "Delete" || event.key === "Backspace") && onRemove) {
17
27
  event.preventDefault();
18
- tabs[index].onRemove();
28
+ onRemove();
19
29
  return;
20
30
  }
21
- if (tabs.length === 0) return;
22
- const nextIndex = event.key === "ArrowRight" || event.key === "ArrowDown" ? index + 1 : event.key === "ArrowLeft" || event.key === "ArrowUp" ? index - 1 : event.key === "Home" ? 0 : event.key === "End" ? tabs.length - 1 : -1;
23
- if (nextIndex === -1) return;
24
- event.preventDefault();
25
- focusTab(nextIndex);
26
- };
27
- const activeTab = tabs[activeIndex];
28
- const activeTabId = activeTab ? `${baseId}-tab-${activeIndex}` : void 0;
29
- const activePanelId = activeTab ? `${baseId}-panel-${activeIndex}` : void 0;
30
- return /* @__PURE__ */ jsxs("div", {
31
- ...rootProps,
32
- className: rootClassName,
31
+ const values = [...tabs.tabs.keys()];
32
+ const index = values.indexOf(value);
33
+ const nextIndex = event.key === "Home" ? 0 : event.key === "End" ? values.length - 1 : event.key === "ArrowRight" || event.key === "ArrowDown" ? (index + 1) % values.length : event.key === "ArrowLeft" || event.key === "ArrowUp" ? (index - 1 + values.length) % values.length : -1;
34
+ if (nextIndex >= 0) {
35
+ event.preventDefault();
36
+ const next = values[nextIndex];
37
+ if (next) {
38
+ tabs.select(next);
39
+ tabs.tabs.get(next)?.focus();
40
+ }
41
+ }
42
+ }
43
+ function setRef(node) {
44
+ if (node) tabs.tabs.set(value, node);
45
+ else tabs.tabs.delete(value);
46
+ if (typeof ref === "function") ref(node);
47
+ else if (ref) ref.current = node;
48
+ }
49
+ return /* @__PURE__ */ jsx("button", {
50
+ ...props,
51
+ "aria-controls": panelId,
52
+ "aria-selected": selected,
53
+ className: [
54
+ "chayns-tabs__tab",
55
+ selected && "chayns-tabs__tab--active",
56
+ className
57
+ ].filter(Boolean).join(" "),
58
+ id: tabId,
59
+ onClick: (event) => {
60
+ onClick?.(event);
61
+ if (!event.defaultPrevented) tabs.select(value);
62
+ },
63
+ onKeyDown: handleKeyDown,
64
+ ref: setRef,
65
+ role: "tab",
66
+ tabIndex: selected ? 0 : -1,
67
+ type: "button",
68
+ children
69
+ });
70
+ });
71
+ var Panel = forwardRef(function Panel({ children, className, value, ...props }, ref) {
72
+ const tabs = useTabs("Panel");
73
+ if (tabs.value !== value) return null;
74
+ return /* @__PURE__ */ jsx("div", {
75
+ ...props,
76
+ "aria-labelledby": `${tabs.baseId}-tab-${value}`,
77
+ className: ["chayns-tabs__panel", className].filter(Boolean).join(" "),
78
+ id: `${tabs.baseId}-panel-${value}`,
33
79
  ref,
34
- children: [/* @__PURE__ */ jsxs("div", {
35
- className: "chayns-tabs__bar",
36
- children: [/* @__PURE__ */ jsx("div", {
37
- className: "chayns-tabs__list",
38
- role: "tablist",
39
- children: tabs.map((tab, index) => {
40
- const tabId = `${baseId}-tab-${index}`;
41
- const panelId = `${baseId}-panel-${index}`;
42
- const isSelected = index === activeIndex;
43
- return /* @__PURE__ */ jsx("div", {
44
- className: "chayns-tabs__item",
45
- role: "presentation",
46
- children: /* @__PURE__ */ jsxs("button", {
47
- "aria-controls": isSelected ? panelId : void 0,
48
- "aria-selected": isSelected,
49
- className: `chayns-tabs__tab${isSelected ? " chayns-tabs__tab--active" : ""}`,
50
- id: tabId,
51
- onClick: (event) => {
52
- if (event.target.closest("[data-tabs-remove]")) {
53
- tab.onRemove?.();
54
- return;
55
- }
56
- tab.onClick();
57
- },
58
- onKeyDown: (event) => handleKeyDown(event, index),
59
- ref: (element) => {
60
- tabRefs.current[index] = element;
61
- },
62
- role: "tab",
63
- tabIndex: isSelected ? 0 : -1,
64
- type: "button",
65
- children: [
66
- /* @__PURE__ */ jsx(TabsIcon, { icon: tab.icon }),
67
- /* @__PURE__ */ jsx("span", {
68
- className: "chayns-tabs__label",
69
- children: tab.name
70
- }),
71
- tab.onRemove ? /* @__PURE__ */ jsx("span", {
72
- "aria-hidden": "true",
73
- className: "chayns-tabs__remove",
74
- "data-tabs-remove": true,
75
- children: /* @__PURE__ */ jsx(TabsIcon, { icon: "fa-xmark" })
76
- }) : null
77
- ]
78
- })
79
- }, tabId);
80
- })
81
- }), onAdd && addLabel ? /* @__PURE__ */ jsx("button", {
82
- "aria-label": addLabel,
83
- className: "chayns-tabs__add",
84
- onClick: onAdd,
85
- type: "button",
86
- children: /* @__PURE__ */ jsx(TabsIcon, { icon: "fa-plus" })
87
- }) : null]
88
- }), activeTab && activeTabId && activePanelId ? /* @__PURE__ */ jsx("div", {
89
- "aria-labelledby": activeTabId,
90
- className: "chayns-tabs__panel",
91
- id: activePanelId,
92
- role: "tabpanel",
93
- tabIndex: 0,
94
- children: activeTab.content
95
- }) : null]
80
+ role: "tabpanel",
81
+ tabIndex: 0,
82
+ children
96
83
  });
97
84
  });
98
- Tabs.displayName = "Tabs";
85
+ var Add = forwardRef(function Add({ children, className, ...props }, ref) {
86
+ useTabs("Add");
87
+ return /* @__PURE__ */ jsx("button", {
88
+ ...props,
89
+ className: ["chayns-tabs__add", className].filter(Boolean).join(" "),
90
+ ref,
91
+ type: "button",
92
+ children
93
+ });
94
+ });
95
+ var Root = forwardRef(function Root({ children, className, defaultValue, onValueChange, value, ...props }, ref) {
96
+ const baseId = useId();
97
+ const [internalValue, setInternalValue] = useState(defaultValue);
98
+ const [tabMap] = useState(() => /* @__PURE__ */ new Map());
99
+ const selectedValue = value ?? internalValue;
100
+ const select = (next) => {
101
+ if (value === void 0) setInternalValue(next);
102
+ onValueChange?.(next);
103
+ };
104
+ return /* @__PURE__ */ jsx(TabsContext.Provider, {
105
+ value: {
106
+ baseId,
107
+ select,
108
+ tabs: tabMap,
109
+ value: selectedValue
110
+ },
111
+ children: /* @__PURE__ */ jsx("div", {
112
+ ...props,
113
+ className: ["chayns-tabs", className].filter(Boolean).join(" "),
114
+ ref,
115
+ children
116
+ })
117
+ });
118
+ });
119
+ var Tabs = Object.assign(Root, {
120
+ Add,
121
+ List,
122
+ Panel,
123
+ Tab
124
+ });
99
125
  //#endregion
100
126
  export { Tabs };
101
127
 
@@ -1 +1 @@
1
- {"version":3,"file":"Tabs.js","names":[],"sources":["../../../src/components/tabs/Tabs.tsx"],"sourcesContent":["import { forwardRef, useId, useRef } from 'react';\nimport type { KeyboardEvent } from 'react';\n\nimport type { TabsProps } from './Tabs.types.js';\nimport TabsIcon from './tabs-icon/TabsIcon.js';\n\nexport const Tabs = forwardRef<HTMLDivElement, TabsProps>(function Tabs(\n { addLabel, className, onAdd, tabs, ...rootProps },\n ref,\n) {\n const baseId = useId();\n const tabRefs = useRef<(HTMLButtonElement | null)[]>([]);\n const activeIndex = Math.max(\n 0,\n tabs.findIndex((tab) => tab.isActive),\n );\n const rootClassName = ['chayns-tabs', className].filter(Boolean).join(' ');\n\n const focusTab = (index: number) => {\n const nextIndex = (index + tabs.length) % tabs.length;\n tabs[nextIndex]?.onClick();\n tabRefs.current[nextIndex]?.focus();\n };\n\n const handleKeyDown = (event: KeyboardEvent<HTMLButtonElement>, index: number) => {\n if ((event.key === 'Delete' || event.key === 'Backspace') && tabs[index]?.onRemove) {\n event.preventDefault();\n tabs[index].onRemove();\n return;\n }\n\n if (tabs.length === 0) return;\n\n const nextIndex =\n event.key === 'ArrowRight' || event.key === 'ArrowDown'\n ? index + 1\n : event.key === 'ArrowLeft' || event.key === 'ArrowUp'\n ? index - 1\n : event.key === 'Home'\n ? 0\n : event.key === 'End'\n ? tabs.length - 1\n : -1;\n\n if (nextIndex === -1) return;\n event.preventDefault();\n focusTab(nextIndex);\n };\n\n const activeTab = tabs[activeIndex];\n const activeTabId = activeTab ? `${baseId}-tab-${activeIndex}` : undefined;\n const activePanelId = activeTab ? `${baseId}-panel-${activeIndex}` : undefined;\n\n return (\n <div {...rootProps} className={rootClassName} ref={ref}>\n <div className=\"chayns-tabs__bar\">\n <div className=\"chayns-tabs__list\" role=\"tablist\">\n {tabs.map((tab, index) => {\n const tabId = `${baseId}-tab-${index}`;\n const panelId = `${baseId}-panel-${index}`;\n const isSelected = index === activeIndex;\n\n return (\n <div className=\"chayns-tabs__item\" key={tabId} role=\"presentation\">\n <button\n aria-controls={isSelected ? panelId : undefined}\n aria-selected={isSelected}\n className={`chayns-tabs__tab${isSelected ? ' chayns-tabs__tab--active' : ''}`}\n id={tabId}\n onClick={(event) => {\n if ((event.target as HTMLElement).closest('[data-tabs-remove]')) {\n tab.onRemove?.();\n return;\n }\n tab.onClick();\n }}\n onKeyDown={(event) => handleKeyDown(event, index)}\n ref={(element) => {\n tabRefs.current[index] = element;\n }}\n role=\"tab\"\n tabIndex={isSelected ? 0 : -1}\n type=\"button\"\n >\n <TabsIcon icon={tab.icon} />\n <span className=\"chayns-tabs__label\">{tab.name}</span>\n {tab.onRemove ? (\n <span aria-hidden=\"true\" className=\"chayns-tabs__remove\" data-tabs-remove>\n <TabsIcon icon=\"fa-xmark\" />\n </span>\n ) : null}\n </button>\n </div>\n );\n })}\n </div>\n {onAdd && addLabel ? (\n <button aria-label={addLabel} className=\"chayns-tabs__add\" onClick={onAdd} type=\"button\">\n <TabsIcon icon=\"fa-plus\" />\n </button>\n ) : null}\n </div>\n {activeTab && activeTabId && activePanelId ? (\n <div\n aria-labelledby={activeTabId}\n className=\"chayns-tabs__panel\"\n id={activePanelId}\n role=\"tabpanel\"\n tabIndex={0}\n >\n {activeTab.content}\n </div>\n ) : null}\n </div>\n );\n});\n\nTabs.displayName = 'Tabs';\n"],"mappings":"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"}
1
+ {"version":3,"file":"Tabs.js","names":[],"sources":["../../../src/components/tabs/Tabs.tsx"],"sourcesContent":["import { createContext, forwardRef, useContext, useId, useState } from 'react';\nimport type { KeyboardEvent } from 'react';\nimport type {\n TabsAddProps,\n TabsListProps,\n TabsPanelProps,\n TabsProps,\n TabsTabProps,\n} from './Tabs.types.js';\n\ninterface TabsContextValue {\n baseId: string;\n select: (value: string) => void;\n tabs: Map<string, HTMLButtonElement>;\n value: string | undefined;\n}\nconst TabsContext = createContext<TabsContextValue | null>(null);\nfunction useTabs(part: string) {\n const context = useContext(TabsContext);\n if (context === null) throw new Error(`Tabs.${part} must be rendered within Tabs.`);\n return context;\n}\n\nconst List = forwardRef<HTMLDivElement, TabsListProps>(function List(\n { children, className, ...props },\n ref,\n) {\n useTabs('List');\n return (\n <div\n {...props}\n className={['chayns-tabs__list', className].filter(Boolean).join(' ')}\n ref={ref}\n role=\"tablist\"\n >\n {children}\n </div>\n );\n});\nconst Tab = forwardRef<HTMLButtonElement, TabsTabProps>(function Tab(\n { children, className, onRemove, onClick, value, ...props },\n ref,\n) {\n const tabs = useTabs('Tab');\n const selected = tabs.value === value;\n const tabId = `${tabs.baseId}-tab-${value}`;\n const panelId = `${tabs.baseId}-panel-${value}`;\n function handleKeyDown(event: KeyboardEvent<HTMLButtonElement>) {\n if ((event.key === 'Delete' || event.key === 'Backspace') && onRemove) {\n event.preventDefault();\n onRemove();\n return;\n }\n const values = [...tabs.tabs.keys()];\n const index = values.indexOf(value);\n const nextIndex =\n event.key === 'Home'\n ? 0\n : event.key === 'End'\n ? values.length - 1\n : event.key === 'ArrowRight' || event.key === 'ArrowDown'\n ? (index + 1) % values.length\n : event.key === 'ArrowLeft' || event.key === 'ArrowUp'\n ? (index - 1 + values.length) % values.length\n : -1;\n if (nextIndex >= 0) {\n event.preventDefault();\n const next = values[nextIndex];\n if (next) {\n tabs.select(next);\n tabs.tabs.get(next)?.focus();\n }\n }\n }\n function setRef(node: HTMLButtonElement | null) {\n if (node) tabs.tabs.set(value, node);\n else tabs.tabs.delete(value);\n if (typeof ref === 'function') ref(node);\n else if (ref) ref.current = node;\n }\n return (\n <button\n {...props}\n aria-controls={panelId}\n aria-selected={selected}\n className={['chayns-tabs__tab', selected && 'chayns-tabs__tab--active', className]\n .filter(Boolean)\n .join(' ')}\n id={tabId}\n onClick={(event) => {\n onClick?.(event);\n if (!event.defaultPrevented) tabs.select(value);\n }}\n onKeyDown={handleKeyDown}\n ref={setRef}\n role=\"tab\"\n tabIndex={selected ? 0 : -1}\n type=\"button\"\n >\n {children}\n </button>\n );\n});\nconst Panel = forwardRef<HTMLDivElement, TabsPanelProps>(function Panel(\n { children, className, value, ...props },\n ref,\n) {\n const tabs = useTabs('Panel');\n if (tabs.value !== value) return null;\n return (\n <div\n {...props}\n aria-labelledby={`${tabs.baseId}-tab-${value}`}\n className={['chayns-tabs__panel', className].filter(Boolean).join(' ')}\n id={`${tabs.baseId}-panel-${value}`}\n ref={ref}\n role=\"tabpanel\"\n tabIndex={0}\n >\n {children}\n </div>\n );\n});\nconst Add = forwardRef<HTMLButtonElement, TabsAddProps>(function Add(\n { children, className, ...props },\n ref,\n) {\n useTabs('Add');\n return (\n <button\n {...props}\n className={['chayns-tabs__add', className].filter(Boolean).join(' ')}\n ref={ref}\n type=\"button\"\n >\n {children}\n </button>\n );\n});\nconst Root = forwardRef<HTMLDivElement, TabsProps>(function Root(\n { children, className, defaultValue, onValueChange, value, ...props },\n ref,\n) {\n const baseId = useId();\n const [internalValue, setInternalValue] = useState(defaultValue);\n const [tabMap] = useState(() => new Map<string, HTMLButtonElement>());\n const selectedValue = value ?? internalValue;\n const select = (next: string) => {\n if (value === undefined) setInternalValue(next);\n onValueChange?.(next);\n };\n return (\n <TabsContext.Provider value={{ baseId, select, tabs: tabMap, value: selectedValue }}>\n <div {...props} className={['chayns-tabs', className].filter(Boolean).join(' ')} ref={ref}>\n {children}\n </div>\n </TabsContext.Provider>\n );\n});\nexport const Tabs = Object.assign(Root, { Add, List, Panel, Tab });\n"],"mappings":"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"}
@@ -1,69 +1,19 @@
1
1
  import type { ComponentPropsWithRef, ReactNode } from 'react';
2
- /**
3
- * @description A FontAwesome Classic icon name in its Regular form, used for
4
- * tab entry icons.
5
- */
6
- export type TabsIcon = `fa-${string}`;
7
- /**
8
- * @description A single tab: its trigger button and the peer content it
9
- * represents. Selection is externally owned `Tabs` never infers or
10
- * reconciles `isActive` itself; the consumer must update it on `onClick`.
11
- */
12
- export interface TabsEntry {
13
- /**
14
- * @description FontAwesome Classic icon name shown on the tab trigger.
15
- */
16
- icon: TabsIcon;
17
- /**
18
- * @description Visible, already-resolved localized tab label.
19
- */
20
- name: string;
21
- /**
22
- * @description Whether this entry is the currently selected tab. Exactly
23
- * one entry in a `tabs` array is expected to be active at a time; the
24
- * consumer, not `Tabs`, is responsible for keeping this consistent.
25
- */
26
- isActive: boolean;
27
- /**
28
- * @description Called when this tab's trigger is activated. The consumer
29
- * is expected to update `isActive` in response.
30
- */
31
- onClick: () => void;
32
- /**
33
- * @description Optional remove handler. When supplied, a remove affordance
34
- * is rendered as part of the same native tab button, and `Delete` or
35
- * `Backspace` triggers it while the tab is focused.
36
- */
2
+ export interface TabsProps extends Omit<ComponentPropsWithRef<'div'>, 'children'> {
3
+ children: ReactNode;
4
+ value?: string;
5
+ defaultValue?: string;
6
+ onValueChange?: (value: string) => void;
7
+ }
8
+ export type TabsListProps = ComponentPropsWithRef<'div'>;
9
+ export interface TabsTabProps extends Omit<ComponentPropsWithRef<'button'>, 'aria-controls' | 'aria-selected' | 'children' | 'role' | 'tabIndex' | 'type'> {
10
+ value: string;
11
+ children: ReactNode;
37
12
  onRemove?: () => void;
38
- /**
39
- * @description Peer panel content for this tab. Only the active entry's
40
- * `content` is rendered.
41
- */
42
- content: ReactNode;
43
13
  }
44
- /**
45
- * @description Props for a tabbed layout pattern that switches between peer
46
- * content regions. `Tabs` owns no routing, persistence, business state or
47
- * translation; selection state lives entirely in `tabs[].isActive`. Forwards
48
- * remaining native `div` props (except `children`, which `Tabs` derives from
49
- * `tabs`), `className` and `ref`.
50
- */
51
- export interface TabsProps extends Omit<ComponentPropsWithRef<'div'>, 'children'> {
52
- /**
53
- * @description Ordered tab entries; exactly one should have `isActive`
54
- * `true`.
55
- */
56
- tabs: TabsEntry[];
57
- /**
58
- * @description Optional handler that renders an add-tab trigger when
59
- * supplied together with `addLabel`.
60
- */
61
- onAdd?: () => void;
62
- /**
63
- * @description Localized accessible name for the add-tab trigger. Required
64
- * for the add trigger to render; supplying `onAdd` without `addLabel` does
65
- * not render the control.
66
- */
67
- addLabel?: string;
14
+ export interface TabsPanelProps extends Omit<ComponentPropsWithRef<'div'>, 'aria-labelledby' | 'children' | 'role'> {
15
+ value: string;
16
+ children: ReactNode;
68
17
  }
18
+ export type TabsAddProps = ComponentPropsWithRef<'button'>;
69
19
  //# sourceMappingURL=Tabs.types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Tabs.types.d.ts","sourceRoot":"","sources":["../../../src/components/tabs/Tabs.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAE9D;;;GAGG;AACH,MAAM,MAAM,QAAQ,GAAG,MAAM,MAAM,EAAE,CAAC;AAEtC;;;;GAIG;AACH,MAAM,WAAW,SAAS;IACxB;;OAEG;IACH,IAAI,EAAE,QAAQ,CAAC;IAEf;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IAEb;;;;OAIG;IACH,QAAQ,EAAE,OAAO,CAAC;IAElB;;;OAGG;IACH,OAAO,EAAE,MAAM,IAAI,CAAC;IAEpB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IAEtB;;;OAGG;IACH,OAAO,EAAE,SAAS,CAAC;CACpB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,SAAU,SAAQ,IAAI,CAAC,qBAAqB,CAAC,KAAK,CAAC,EAAE,UAAU,CAAC;IAC/E;;;OAGG;IACH,IAAI,EAAE,SAAS,EAAE,CAAC;IAElB;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,IAAI,CAAC;IAEnB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB"}
1
+ {"version":3,"file":"Tabs.types.d.ts","sourceRoot":"","sources":["../../../src/components/tabs/Tabs.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAE9D,MAAM,WAAW,SAAU,SAAQ,IAAI,CAAC,qBAAqB,CAAC,KAAK,CAAC,EAAE,UAAU,CAAC;IAC/E,QAAQ,EAAE,SAAS,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACzC;AACD,MAAM,MAAM,aAAa,GAAG,qBAAqB,CAAC,KAAK,CAAC,CAAC;AACzD,MAAM,WAAW,YAAa,SAAQ,IAAI,CACxC,qBAAqB,CAAC,QAAQ,CAAC,EAC/B,eAAe,GAAG,eAAe,GAAG,UAAU,GAAG,MAAM,GAAG,UAAU,GAAG,MAAM,CAC9E;IACC,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,SAAS,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;CACvB;AACD,MAAM,WAAW,cAAe,SAAQ,IAAI,CAC1C,qBAAqB,CAAC,KAAK,CAAC,EAC5B,iBAAiB,GAAG,UAAU,GAAG,MAAM,CACxC;IACC,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,SAAS,CAAC;CACrB;AACD,MAAM,MAAM,YAAY,GAAG,qBAAqB,CAAC,QAAQ,CAAC,CAAC"}
@@ -1,6 +1,6 @@
1
- import type { TabsEntry } from '../Tabs.types.js';
1
+ type TabsIconName = `fa-${string}`;
2
2
  declare const TabsIcon: ({ icon }: {
3
- icon: TabsEntry["icon"];
3
+ icon: TabsIconName;
4
4
  }) => import("react").JSX.Element;
5
5
  export default TabsIcon;
6
6
  //# sourceMappingURL=TabsIcon.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"TabsIcon.d.ts","sourceRoot":"","sources":["../../../../src/components/tabs/tabs-icon/TabsIcon.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAElD,QAAA,MAAM,QAAQ,GAAI,UAAU;IAAE,IAAI,EAAE,SAAS,CAAC,MAAM,CAAC,CAAA;CAAE,gCAItD,CAAC;AAEF,eAAe,QAAQ,CAAC"}
1
+ {"version":3,"file":"TabsIcon.d.ts","sourceRoot":"","sources":["../../../../src/components/tabs/tabs-icon/TabsIcon.tsx"],"names":[],"mappings":"AAAA,KAAK,YAAY,GAAG,MAAM,MAAM,EAAE,CAAC;AAEnC,QAAA,MAAM,QAAQ,GAAI,UAAU;IAAE,IAAI,EAAE,YAAY,CAAA;CAAE,gCAIjD,CAAC;AAEF,eAAe,QAAQ,CAAC"}
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  export { AppLayout } from './components/app-layout/AppLayout.js';
2
- export type { AppLayoutIcon, AppLayoutItem, AppLayoutProps, } from './components/app-layout/AppLayout.types.js';
2
+ export type { AppLayoutCollapseToggleProps, AppLayoutContentProps, AppLayoutHeaderProps, AppLayoutLogoProps, AppLayoutNavigationItemProps, AppLayoutNavigationProps, AppLayoutProps, } from './components/app-layout/AppLayout.types.js';
3
3
  export { Tabs } from './components/tabs/Tabs.js';
4
- export type { TabsEntry, TabsIcon, TabsProps } from './components/tabs/Tabs.types.js';
4
+ export type { TabsAddProps, TabsListProps, TabsPanelProps, TabsProps, TabsTabProps, } from './components/tabs/Tabs.types.js';
5
5
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,sCAAsC,CAAC;AACjE,YAAY,EACV,aAAa,EACb,aAAa,EACb,cAAc,GACf,MAAM,4CAA4C,CAAC;AACpD,OAAO,EAAE,IAAI,EAAE,MAAM,2BAA2B,CAAC;AACjD,YAAY,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,iCAAiC,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,sCAAsC,CAAC;AACjE,YAAY,EACV,4BAA4B,EAC5B,qBAAqB,EACrB,oBAAoB,EACpB,kBAAkB,EAClB,4BAA4B,EAC5B,wBAAwB,EACxB,cAAc,GACf,MAAM,4CAA4C,CAAC;AACpD,OAAO,EAAE,IAAI,EAAE,MAAM,2BAA2B,CAAC;AACjD,YAAY,EACV,YAAY,EACZ,aAAa,EACb,cAAc,EACd,SAAS,EACT,YAAY,GACb,MAAM,iCAAiC,CAAC"}
package/dist/tabs.css CHANGED
@@ -123,9 +123,10 @@
123
123
  flex: 1 1 auto;
124
124
  min-inline-size: 0;
125
125
  min-block-size: 0;
126
- padding: var(--sp-4);
126
+ padding: var(--sp-2);
127
127
  overflow: auto;
128
128
  background: var(--surface);
129
+ color: var(--text);
129
130
  }
130
131
 
131
132
  @container (max-width: 20rem) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@chayns-ui/layout",
3
- "version": "0.4.0",
3
+ "version": "0.6.0",
4
4
  "description": "Accessible application layout components for chayns UI",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -28,11 +28,11 @@
28
28
  "./package.json": "./package.json"
29
29
  },
30
30
  "peerDependencies": {
31
- "@chayns-ui/core": ">=0.3.0",
31
+ "@chayns-ui/core": ">=0.4.0",
32
32
  "react": ">=18 <20"
33
33
  },
34
34
  "devDependencies": {
35
- "@chayns-ui/core": "0.3.0"
35
+ "@chayns-ui/core": "0.4.0"
36
36
  },
37
37
  "engines": {
38
38
  "node": ">=18"
@@ -1,17 +0,0 @@
1
- import { jsx, jsxs } from "react/jsx-runtime";
2
- //#region src/components/app-layout/app-layout-icon/AppLayoutIcon.tsx
3
- var AppLayoutIcon = ({ icon }) => /* @__PURE__ */ jsxs("span", {
4
- "aria-hidden": "true",
5
- className: "chayns-app-layout__icon",
6
- children: [/* @__PURE__ */ jsx("span", {
7
- className: "chayns-app-layout__weight",
8
- children: /* @__PURE__ */ jsx("i", { className: `far ${icon}` })
9
- }), /* @__PURE__ */ jsx("span", {
10
- className: "chayns-app-layout__weight chayns-app-layout__weight--active",
11
- children: /* @__PURE__ */ jsx("i", { className: `fas ${icon}` })
12
- })]
13
- });
14
- //#endregion
15
- export { AppLayoutIcon as default };
16
-
17
- //# sourceMappingURL=AppLayoutIcon.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"AppLayoutIcon.js","names":[],"sources":["../../../../src/components/app-layout/app-layout-icon/AppLayoutIcon.tsx"],"sourcesContent":["import type { AppLayoutItem } from '../AppLayout.types.js';\n\nconst AppLayoutIcon = ({ icon }: { icon: AppLayoutItem['icon'] }) => (\n <span aria-hidden=\"true\" className=\"chayns-app-layout__icon\">\n <span className=\"chayns-app-layout__weight\">\n <i className={`far ${icon}`} />\n </span>\n <span className=\"chayns-app-layout__weight chayns-app-layout__weight--active\">\n <i className={`fas ${icon}`} />\n </span>\n </span>\n);\n\nexport default AppLayoutIcon;\n"],"mappings":";;AAEA,IAAM,iBAAiB,EAAE,WACvB,qBAAC,QAAD;CAAM,eAAY;CAAO,WAAU;CAAnC,UAAA,CACE,oBAAC,QAAD;EAAM,WAAU;EACd,UAAA,oBAAC,KAAD,EAAG,WAAW,OAAO,OAAS,CAAA;CAC1B,CAAA,GACN,oBAAC,QAAD;EAAM,WAAU;EACd,UAAA,oBAAC,KAAD,EAAG,WAAW,OAAO,OAAS,CAAA;CAC1B,CAAA,CACF"}
@@ -1,13 +0,0 @@
1
- import type { AppLayoutItem } from '../AppLayout.types.js';
2
- interface NavigationItemsProps {
3
- items: AppLayoutItem[];
4
- activeItemId?: string | undefined;
5
- collapsed: boolean;
6
- onClick: (id: string) => void;
7
- expandedIds: ReadonlySet<string>;
8
- onToggle: (id: string) => void;
9
- parentId?: string;
10
- }
11
- declare const NavigationItems: ({ activeItemId, collapsed, expandedIds, items, onClick, onToggle, parentId, }: NavigationItemsProps) => import("react").JSX.Element;
12
- export default NavigationItems;
13
- //# sourceMappingURL=NavigationItems.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"NavigationItems.d.ts","sourceRoot":"","sources":["../../../../src/components/app-layout/navigation-items/NavigationItems.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAE3D,UAAU,oBAAoB;IAC5B,KAAK,EAAE,aAAa,EAAE,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9B,WAAW,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IACjC,QAAQ,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/B,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,QAAA,MAAM,eAAe,GAAI,+EAQtB,oBAAoB,gCAoEtB,CAAC;AAEF,eAAe,eAAe,CAAC"}
@@ -1,54 +0,0 @@
1
- import AppLayoutIcon from "../app-layout-icon/AppLayoutIcon.js";
2
- import { jsx, jsxs } from "react/jsx-runtime";
3
- //#region src/components/app-layout/navigation-items/NavigationItems.tsx
4
- var NavigationItems = ({ activeItemId, collapsed, expandedIds, items, onClick, onToggle, parentId }) => /* @__PURE__ */ jsx("ul", {
5
- className: "chayns-app-layout__list",
6
- children: items.map((item) => {
7
- const hasChildren = Boolean(item.children?.length);
8
- const isExpanded = expandedIds.has(item.id);
9
- const panelId = `${parentId ?? "root"}-${item.id}-children`;
10
- return /* @__PURE__ */ jsxs("li", {
11
- className: `chayns-app-layout__item${activeItemId === item.id ? " chayns-app-layout__item--active" : ""}`,
12
- children: [/* @__PURE__ */ jsxs("div", {
13
- className: "chayns-app-layout__row",
14
- children: [/* @__PURE__ */ jsxs("button", {
15
- "aria-current": activeItemId === item.id ? "page" : void 0,
16
- "aria-label": item.name,
17
- className: "chayns-app-layout__action",
18
- onClick: () => onClick(item.id),
19
- type: "button",
20
- children: [/* @__PURE__ */ jsx(AppLayoutIcon, { icon: item.icon }), /* @__PURE__ */ jsx("span", {
21
- className: `chayns-app-layout__label${collapsed ? " chayns-app-layout__label--hidden" : ""}`,
22
- children: item.name
23
- })]
24
- }), hasChildren && !collapsed ? /* @__PURE__ */ jsx("button", {
25
- "aria-controls": panelId,
26
- "aria-expanded": isExpanded,
27
- "aria-label": item.name,
28
- className: "chayns-app-layout__disclosure",
29
- onClick: () => onToggle(item.id),
30
- type: "button",
31
- children: /* @__PURE__ */ jsx(AppLayoutIcon, { icon: "fa-chevron-down" })
32
- }) : null]
33
- }), hasChildren && !collapsed ? /* @__PURE__ */ jsx("div", {
34
- "aria-hidden": !isExpanded,
35
- className: `chayns-app-layout__children${isExpanded ? " chayns-app-layout__children--open" : ""}`,
36
- id: panelId,
37
- inert: !isExpanded,
38
- children: /* @__PURE__ */ jsx(NavigationItems, {
39
- activeItemId,
40
- collapsed,
41
- expandedIds,
42
- items: item.children ?? [],
43
- onClick,
44
- onToggle,
45
- parentId: item.id
46
- })
47
- }) : null]
48
- }, item.id);
49
- })
50
- });
51
- //#endregion
52
- export { NavigationItems as default };
53
-
54
- //# sourceMappingURL=NavigationItems.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"NavigationItems.js","names":[],"sources":["../../../../src/components/app-layout/navigation-items/NavigationItems.tsx"],"sourcesContent":["import AppLayoutIcon from '../app-layout-icon/AppLayoutIcon.js';\nimport type { AppLayoutItem } from '../AppLayout.types.js';\n\ninterface NavigationItemsProps {\n items: AppLayoutItem[];\n activeItemId?: string | undefined;\n collapsed: boolean;\n onClick: (id: string) => void;\n expandedIds: ReadonlySet<string>;\n onToggle: (id: string) => void;\n parentId?: string;\n}\n\nconst NavigationItems = ({\n activeItemId,\n collapsed,\n expandedIds,\n items,\n onClick,\n onToggle,\n parentId,\n}: NavigationItemsProps) => (\n <ul className=\"chayns-app-layout__list\">\n {items.map((item) => {\n const hasChildren = Boolean(item.children?.length);\n const isExpanded = expandedIds.has(item.id);\n const panelId = `${parentId ?? 'root'}-${item.id}-children`;\n\n return (\n <li\n className={`chayns-app-layout__item${\n activeItemId === item.id ? ' chayns-app-layout__item--active' : ''\n }`}\n key={item.id}\n >\n <div className=\"chayns-app-layout__row\">\n <button\n aria-current={activeItemId === item.id ? 'page' : undefined}\n aria-label={item.name}\n className=\"chayns-app-layout__action\"\n onClick={() => onClick(item.id)}\n type=\"button\"\n >\n <AppLayoutIcon icon={item.icon} />\n <span\n className={`chayns-app-layout__label${\n collapsed ? ' chayns-app-layout__label--hidden' : ''\n }`}\n >\n {item.name}\n </span>\n </button>\n {hasChildren && !collapsed ? (\n <button\n aria-controls={panelId}\n aria-expanded={isExpanded}\n aria-label={item.name}\n className=\"chayns-app-layout__disclosure\"\n onClick={() => onToggle(item.id)}\n type=\"button\"\n >\n <AppLayoutIcon icon=\"fa-chevron-down\" />\n </button>\n ) : null}\n </div>\n {hasChildren && !collapsed ? (\n <div\n aria-hidden={!isExpanded}\n className={`chayns-app-layout__children${\n isExpanded ? ' chayns-app-layout__children--open' : ''\n }`}\n id={panelId}\n inert={!isExpanded}\n >\n <NavigationItems\n activeItemId={activeItemId}\n collapsed={collapsed}\n expandedIds={expandedIds}\n items={item.children ?? []}\n onClick={onClick}\n onToggle={onToggle}\n parentId={item.id}\n />\n </div>\n ) : null}\n </li>\n );\n })}\n </ul>\n);\n\nexport default NavigationItems;\n"],"mappings":";;;AAaA,IAAM,mBAAmB,EACvB,cACA,WACA,aACA,OACA,SACA,UACA,eAEA,oBAAC,MAAD;CAAI,WAAU;CACX,UAAA,MAAM,KAAK,SAAS;EACnB,MAAM,cAAc,QAAQ,KAAK,UAAU,MAAM;EACjD,MAAM,aAAa,YAAY,IAAI,KAAK,EAAE;EAC1C,MAAM,UAAU,GAAG,YAAY,OAAO,GAAG,KAAK,GAAG;EAEjD,OACE,qBAAC,MAAD;GACE,WAAW,0BACT,iBAAiB,KAAK,KAAK,qCAAqC;GAFpE,UAAA,CAME,qBAAC,OAAD;IAAK,WAAU;IAAf,UAAA,CACE,qBAAC,UAAD;KACE,gBAAc,iBAAiB,KAAK,KAAK,SAAS,KAAA;KAClD,cAAY,KAAK;KACjB,WAAU;KACV,eAAe,QAAQ,KAAK,EAAE;KAC9B,MAAK;KALP,UAAA,CAOE,oBAAC,eAAD,EAAe,MAAM,KAAK,KAAO,CAAA,GACjC,oBAAC,QAAD;MACE,WAAW,2BACT,YAAY,sCAAsC;MAGnD,UAAA,KAAK;KACF,CAAA,CACA;IACP,CAAA,GAAA,eAAe,CAAC,YACf,oBAAC,UAAD;KACE,iBAAe;KACf,iBAAe;KACf,cAAY,KAAK;KACjB,WAAU;KACV,eAAe,SAAS,KAAK,EAAE;KAC/B,MAAK;KAEL,UAAA,oBAAC,eAAD,EAAe,MAAK,kBAAmB,CAAA;IACjC,CAAA,IACN,IACD;GACJ,CAAA,GAAA,eAAe,CAAC,YACf,oBAAC,OAAD;IACE,eAAa,CAAC;IACd,WAAW,8BACT,aAAa,uCAAuC;IAEtD,IAAI;IACJ,OAAO,CAAC;IAER,UAAA,oBAAC,iBAAD;KACgB;KACH;KACE;KACb,OAAO,KAAK,YAAY,CAAC;KAChB;KACC;KACV,UAAU,KAAK;IAChB,CAAA;GACE,CAAA,IACH,IACF;EApDG,GAAA,KAAK,EAoDR;CAER,CAAC;AACC,CAAA"}
@@ -1,11 +0,0 @@
1
- import { jsx } from "react/jsx-runtime";
2
- //#region src/components/tabs/tabs-icon/TabsIcon.tsx
3
- var TabsIcon = ({ icon }) => /* @__PURE__ */ jsx("span", {
4
- "aria-hidden": "true",
5
- className: "chayns-tabs__icon",
6
- children: /* @__PURE__ */ jsx("i", { className: `far ${icon}` })
7
- });
8
- //#endregion
9
- export { TabsIcon as default };
10
-
11
- //# sourceMappingURL=TabsIcon.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"TabsIcon.js","names":[],"sources":["../../../../src/components/tabs/tabs-icon/TabsIcon.tsx"],"sourcesContent":["import type { TabsEntry } from '../Tabs.types.js';\n\nconst TabsIcon = ({ icon }: { icon: TabsEntry['icon'] }) => (\n <span aria-hidden=\"true\" className=\"chayns-tabs__icon\">\n <i className={`far ${icon}`} />\n </span>\n);\n\nexport default TabsIcon;\n"],"mappings":";;AAEA,IAAM,YAAY,EAAE,WAClB,oBAAC,QAAD;CAAM,eAAY;CAAO,WAAU;CACjC,UAAA,oBAAC,KAAD,EAAG,WAAW,OAAO,OAAS,CAAA;AAC1B,CAAA"}