@cratis/scene.react 4.3.0 → 4.5.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 (65) hide show
  1. package/core/CoreNavigationBar.tsx +8 -2
  2. package/dist/cjs/core/CoreNavigationBar.js +13 -3
  3. package/dist/cjs/core/CoreNavigationBar.js.map +1 -1
  4. package/dist/cjs/icons/IconAdapterContext.js +21 -0
  5. package/dist/cjs/icons/IconAdapterContext.js.map +1 -0
  6. package/dist/cjs/icons/IconAdapterRegistry.js +45 -0
  7. package/dist/cjs/icons/IconAdapterRegistry.js.map +1 -0
  8. package/dist/cjs/icons/SceneIcon.js +42 -0
  9. package/dist/cjs/icons/SceneIcon.js.map +1 -0
  10. package/dist/cjs/icons/useIconGlyph.js +86 -0
  11. package/dist/cjs/icons/useIconGlyph.js.map +1 -0
  12. package/dist/cjs/index.js +11 -0
  13. package/dist/cjs/index.js.map +1 -1
  14. package/dist/cjs/packages/ScenePackageBundle.js +41 -0
  15. package/dist/cjs/packages/ScenePackageBundle.js.map +1 -1
  16. package/dist/esm/core/CoreNavigationBar.d.ts.map +1 -1
  17. package/dist/esm/core/CoreNavigationBar.js +14 -4
  18. package/dist/esm/core/CoreNavigationBar.js.map +1 -1
  19. package/dist/esm/icons/IconAdapter.d.ts +13 -0
  20. package/dist/esm/icons/IconAdapter.d.ts.map +1 -0
  21. package/dist/esm/icons/IconAdapter.js +2 -0
  22. package/dist/esm/icons/IconAdapter.js.map +1 -0
  23. package/dist/esm/icons/IconAdapterContext.d.ts +8 -0
  24. package/dist/esm/icons/IconAdapterContext.d.ts.map +1 -0
  25. package/dist/esm/icons/IconAdapterContext.js +18 -0
  26. package/dist/esm/icons/IconAdapterContext.js.map +1 -0
  27. package/dist/esm/icons/IconAdapterRegistry.d.ts +9 -0
  28. package/dist/esm/icons/IconAdapterRegistry.d.ts.map +1 -0
  29. package/dist/esm/icons/IconAdapterRegistry.js +42 -0
  30. package/dist/esm/icons/IconAdapterRegistry.js.map +1 -0
  31. package/dist/esm/icons/IconLibraryBundle.d.ts +7 -0
  32. package/dist/esm/icons/IconLibraryBundle.d.ts.map +1 -0
  33. package/dist/esm/icons/IconLibraryBundle.js +2 -0
  34. package/dist/esm/icons/IconLibraryBundle.js.map +1 -0
  35. package/dist/esm/icons/SceneIcon.d.ts +14 -0
  36. package/dist/esm/icons/SceneIcon.d.ts.map +1 -0
  37. package/dist/esm/icons/SceneIcon.js +40 -0
  38. package/dist/esm/icons/SceneIcon.js.map +1 -0
  39. package/dist/esm/icons/index.d.ts +7 -0
  40. package/dist/esm/icons/index.d.ts.map +1 -0
  41. package/dist/esm/icons/index.js +7 -0
  42. package/dist/esm/icons/index.js.map +1 -0
  43. package/dist/esm/icons/useIconGlyph.d.ts +14 -0
  44. package/dist/esm/icons/useIconGlyph.d.ts.map +1 -0
  45. package/dist/esm/icons/useIconGlyph.js +84 -0
  46. package/dist/esm/icons/useIconGlyph.js.map +1 -0
  47. package/dist/esm/index.d.ts +1 -0
  48. package/dist/esm/index.d.ts.map +1 -1
  49. package/dist/esm/index.js +5 -1
  50. package/dist/esm/index.js.map +1 -1
  51. package/dist/esm/packages/ScenePackageBundle.d.ts +4 -0
  52. package/dist/esm/packages/ScenePackageBundle.d.ts.map +1 -1
  53. package/dist/esm/packages/ScenePackageBundle.js +42 -2
  54. package/dist/esm/packages/ScenePackageBundle.js.map +1 -1
  55. package/dist/esm/tsconfig.tsbuildinfo +1 -1
  56. package/icons/IconAdapter.ts +52 -0
  57. package/icons/IconAdapterContext.tsx +21 -0
  58. package/icons/IconAdapterRegistry.ts +50 -0
  59. package/icons/IconLibraryBundle.ts +25 -0
  60. package/icons/SceneIcon.tsx +73 -0
  61. package/icons/index.ts +9 -0
  62. package/icons/useIconGlyph.ts +79 -0
  63. package/index.ts +1 -0
  64. package/package.json +5 -5
  65. package/packages/ScenePackageBundle.ts +58 -1
@@ -1,12 +1,15 @@
1
1
  // Copyright (c) Cratis. All rights reserved.
2
2
  // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3
3
 
4
+ import { IconReference } from '@cratis/scene.model';
5
+ import { useIconAdapters } from '../icons/IconAdapterContext';
6
+ import { SceneIcon } from '../icons/SceneIcon';
4
7
  import { RegisteredComponentProps } from '../renderer';
5
8
 
6
9
  interface NavigationBarItem {
7
10
  id: string;
8
11
  label: string;
9
- icon?: { library: string; key: string; variant?: string };
12
+ icon?: IconReference;
10
13
  destination?: { screen: string };
11
14
  }
12
15
 
@@ -22,10 +25,12 @@ function isNavigationBarItem(value: unknown): value is NavigationBarItem {
22
25
  * It reads `items` from the property bag it is given and nothing else, so it renders the same whether a screen is
23
26
  * being played or edited - configuration is resolved into the bag before it gets here. An item names its destination
24
27
  * as a screen, and activating it emits a host-neutral navigation event, the same as `core:navigate`. An item's icon
25
- * is carried on the node as data attributes for a host to render; icon catalogs are not this component's business.
28
+ * is carried on the node as data attributes and, when an `IconAdapterProvider` is in scope, drawn through the adapter
29
+ * for its library; without one the item shows its label alone. Which icons exist is not this component's business.
26
30
  */
27
31
  export function CoreNavigationBar({ element }: RegisteredComponentProps) {
28
32
  const items = Array.isArray(element.properties.items) ? element.properties.items.filter(isNavigationBarItem) : [];
33
+ const adapters = useIconAdapters();
29
34
  const title = typeof element.properties.title === 'string' ? element.properties.title : undefined;
30
35
 
31
36
  return (
@@ -44,6 +49,7 @@ export function CoreNavigationBar({ element }: RegisteredComponentProps) {
44
49
  disabled={targetScreen === ''}
45
50
  onClick={navigate}
46
51
  >
52
+ {item.icon && adapters ? <SceneIcon reference={item.icon} adapters={adapters} /> : null}
47
53
  {item.label}
48
54
  </button>
49
55
  );
@@ -1,6 +1,8 @@
1
1
  'use strict';
2
2
 
3
3
  var jsxRuntime = require('react/jsx-runtime');
4
+ var IconAdapterContext = require('../icons/IconAdapterContext.js');
5
+ var SceneIcon = require('../icons/SceneIcon.js');
4
6
 
5
7
  // Copyright (c) Cratis. All rights reserved.
6
8
  // Licensed under the MIT license. See LICENSE file in the project root for full license information.
@@ -15,9 +17,11 @@ function isNavigationBarItem(value) {
15
17
  * It reads `items` from the property bag it is given and nothing else, so it renders the same whether a screen is
16
18
  * being played or edited - configuration is resolved into the bag before it gets here. An item names its destination
17
19
  * as a screen, and activating it emits a host-neutral navigation event, the same as `core:navigate`. An item's icon
18
- * is carried on the node as data attributes for a host to render; icon catalogs are not this component's business.
20
+ * is carried on the node as data attributes and, when an `IconAdapterProvider` is in scope, drawn through the adapter
21
+ * for its library; without one the item shows its label alone. Which icons exist is not this component's business.
19
22
  */ function CoreNavigationBar({ element }) {
20
23
  const items = Array.isArray(element.properties.items) ? element.properties.items.filter(isNavigationBarItem) : [];
24
+ const adapters = IconAdapterContext.useIconAdapters();
21
25
  const title = typeof element.properties.title === 'string' ? element.properties.title : undefined;
22
26
  return /*#__PURE__*/ jsxRuntime.jsx("nav", {
23
27
  "data-scene-id": element.id,
@@ -31,7 +35,7 @@ function isNavigationBarItem(value) {
31
35
  item
32
36
  }
33
37
  }));
34
- return /*#__PURE__*/ jsxRuntime.jsx("button", {
38
+ return /*#__PURE__*/ jsxRuntime.jsxs("button", {
35
39
  type: "button",
36
40
  "data-scene-item": item.id,
37
41
  "data-scene-icon-library": item.icon?.library,
@@ -39,7 +43,13 @@ function isNavigationBarItem(value) {
39
43
  "data-scene-icon-variant": item.icon?.variant,
40
44
  disabled: targetScreen === '',
41
45
  onClick: navigate,
42
- children: item.label
46
+ children: [
47
+ item.icon && adapters ? /*#__PURE__*/ jsxRuntime.jsx(SceneIcon.SceneIcon, {
48
+ reference: item.icon,
49
+ adapters: adapters
50
+ }) : null,
51
+ item.label
52
+ ]
43
53
  }, item.id);
44
54
  })
45
55
  });
@@ -1 +1 @@
1
- {"version":3,"file":"CoreNavigationBar.js","sources":["../../../core/CoreNavigationBar.tsx"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { RegisteredComponentProps } from '../renderer';\n\ninterface NavigationBarItem {\n id: string;\n label: string;\n icon?: { library: string; key: string; variant?: string };\n destination?: { screen: string };\n}\n\nfunction isNavigationBarItem(value: unknown): value is NavigationBarItem {\n const candidate = value as Partial<NavigationBarItem> | null;\n return candidate !== null && typeof candidate === 'object' && typeof candidate.id === 'string' && typeof candidate.label === 'string';\n}\n\n/**\n * The `core:navigationBar` component: a list of navigation items, the first of which a template author normally\n * fixes as Home and the rest of which consumers of the template can add to.\n *\n * It reads `items` from the property bag it is given and nothing else, so it renders the same whether a screen is\n * being played or edited - configuration is resolved into the bag before it gets here. An item names its destination\n * as a screen, and activating it emits a host-neutral navigation event, the same as `core:navigate`. An item's icon\n * is carried on the node as data attributes for a host to render; icon catalogs are not this component's business.\n */\nexport function CoreNavigationBar({ element }: RegisteredComponentProps) {\n const items = Array.isArray(element.properties.items) ? element.properties.items.filter(isNavigationBarItem) : [];\n const title = typeof element.properties.title === 'string' ? element.properties.title : undefined;\n\n return (\n <nav data-scene-id={element.id} aria-label={title}>\n {items.map(item => {\n const targetScreen = item.destination?.screen ?? '';\n const navigate = () => globalThis.dispatchEvent(new CustomEvent('cratis.scene.navigate', { detail: { targetScreen, element, item } }));\n return (\n <button\n key={item.id}\n type='button'\n data-scene-item={item.id}\n data-scene-icon-library={item.icon?.library}\n data-scene-icon-key={item.icon?.key}\n data-scene-icon-variant={item.icon?.variant}\n disabled={targetScreen === ''}\n onClick={navigate}\n >\n {item.label}\n </button>\n );\n })}\n </nav>\n );\n}\n"],"names":["isNavigationBarItem","value","candidate","id","label","CoreNavigationBar","element","items","Array","isArray","properties","filter","title","undefined","_jsx","nav","data-scene-id","aria-label","map","item","targetScreen","destination","screen","navigate","globalThis","dispatchEvent","CustomEvent","detail","button","type","data-scene-item","data-scene-icon-library","icon","library","data-scene-icon-key","key","data-scene-icon-variant","variant","disabled","onClick"],"mappings":";;;;AAAA;AACA;AAWA,SAASA,oBAAoBC,KAAc,EAAA;AACvC,IAAA,MAAMC,SAAAA,GAAYD,KAAAA;AAClB,IAAA,OAAOC,SAAAA,KAAc,IAAA,IAAQ,OAAOA,SAAAA,KAAc,QAAA,IAAY,OAAOA,SAAAA,CAAUC,EAAE,KAAK,QAAA,IAAY,OAAOD,SAAAA,CAAUE,KAAK,KAAK,QAAA;AACjI;AAEA;;;;;;;;AAQC,IACM,SAASC,iBAAAA,CAAkB,EAAEC,OAAO,EAA4B,EAAA;AACnE,IAAA,MAAMC,QAAQC,KAAAA,CAAMC,OAAO,CAACH,OAAAA,CAAQI,UAAU,CAACH,KAAK,CAAA,GAAID,OAAAA,CAAQI,UAAU,CAACH,KAAK,CAACI,MAAM,CAACX,uBAAuB,EAAE;AACjH,IAAA,MAAMY,KAAAA,GAAQ,OAAON,OAAAA,CAAQI,UAAU,CAACE,KAAK,KAAK,QAAA,GAAWN,OAAAA,CAAQI,UAAU,CAACE,KAAK,GAAGC,SAAAA;AAExF,IAAA,qBACIC,cAAA,CAACC,KAAAA,EAAAA;AAAIC,QAAAA,eAAAA,EAAeV,QAAQH,EAAE;QAAEc,YAAAA,EAAYL,KAAAA;kBACvCL,KAAAA,CAAMW,GAAG,CAACC,CAAAA,IAAAA,GAAAA;AACP,YAAA,MAAMC,YAAAA,GAAeD,IAAAA,CAAKE,WAAW,EAAEC,MAAAA,IAAU,EAAA;AACjD,YAAA,MAAMC,WAAW,IAAMC,UAAAA,CAAWC,aAAa,CAAC,IAAIC,YAAY,uBAAA,EAAyB;oBAAEC,MAAAA,EAAQ;AAAEP,wBAAAA,YAAAA;AAAcd,wBAAAA,OAAAA;AAASa,wBAAAA;AAAK;AAAE,iBAAA,CAAA,CAAA;AACnI,YAAA,qBACIL,cAAA,CAACc,QAAAA,EAAAA;gBAEGC,IAAAA,EAAK,QAAA;AACLC,gBAAAA,iBAAAA,EAAiBX,KAAKhB,EAAE;gBACxB4B,yBAAAA,EAAyBZ,IAAAA,CAAKa,IAAI,EAAEC,OAAAA;gBACpCC,qBAAAA,EAAqBf,IAAAA,CAAKa,IAAI,EAAEG,GAAAA;gBAChCC,yBAAAA,EAAyBjB,IAAAA,CAAKa,IAAI,EAAEK,OAAAA;AACpCC,gBAAAA,QAAAA,EAAUlB,YAAAA,KAAiB,EAAA;gBAC3BmB,OAAAA,EAAShB,QAAAA;AAERJ,gBAAAA,QAAAA,EAAAA,IAAAA,CAAKf;AATDe,aAAAA,EAAAA,IAAAA,CAAKhB,EAAE,CAAA;AAYxB,QAAA,CAAA;;AAGZ;;"}
1
+ {"version":3,"file":"CoreNavigationBar.js","sources":["../../../core/CoreNavigationBar.tsx"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { IconReference } from '@cratis/scene.model';\nimport { useIconAdapters } from '../icons/IconAdapterContext';\nimport { SceneIcon } from '../icons/SceneIcon';\nimport { RegisteredComponentProps } from '../renderer';\n\ninterface NavigationBarItem {\n id: string;\n label: string;\n icon?: IconReference;\n destination?: { screen: string };\n}\n\nfunction isNavigationBarItem(value: unknown): value is NavigationBarItem {\n const candidate = value as Partial<NavigationBarItem> | null;\n return candidate !== null && typeof candidate === 'object' && typeof candidate.id === 'string' && typeof candidate.label === 'string';\n}\n\n/**\n * The `core:navigationBar` component: a list of navigation items, the first of which a template author normally\n * fixes as Home and the rest of which consumers of the template can add to.\n *\n * It reads `items` from the property bag it is given and nothing else, so it renders the same whether a screen is\n * being played or edited - configuration is resolved into the bag before it gets here. An item names its destination\n * as a screen, and activating it emits a host-neutral navigation event, the same as `core:navigate`. An item's icon\n * is carried on the node as data attributes and, when an `IconAdapterProvider` is in scope, drawn through the adapter\n * for its library; without one the item shows its label alone. Which icons exist is not this component's business.\n */\nexport function CoreNavigationBar({ element }: RegisteredComponentProps) {\n const items = Array.isArray(element.properties.items) ? element.properties.items.filter(isNavigationBarItem) : [];\n const adapters = useIconAdapters();\n const title = typeof element.properties.title === 'string' ? element.properties.title : undefined;\n\n return (\n <nav data-scene-id={element.id} aria-label={title}>\n {items.map(item => {\n const targetScreen = item.destination?.screen ?? '';\n const navigate = () => globalThis.dispatchEvent(new CustomEvent('cratis.scene.navigate', { detail: { targetScreen, element, item } }));\n return (\n <button\n key={item.id}\n type='button'\n data-scene-item={item.id}\n data-scene-icon-library={item.icon?.library}\n data-scene-icon-key={item.icon?.key}\n data-scene-icon-variant={item.icon?.variant}\n disabled={targetScreen === ''}\n onClick={navigate}\n >\n {item.icon && adapters ? <SceneIcon reference={item.icon} adapters={adapters} /> : null}\n {item.label}\n </button>\n );\n })}\n </nav>\n );\n}\n"],"names":["isNavigationBarItem","value","candidate","id","label","CoreNavigationBar","element","items","Array","isArray","properties","filter","adapters","useIconAdapters","title","undefined","_jsx","nav","data-scene-id","aria-label","map","item","targetScreen","destination","screen","navigate","globalThis","dispatchEvent","CustomEvent","detail","_jsxs","button","type","data-scene-item","data-scene-icon-library","icon","library","data-scene-icon-key","key","data-scene-icon-variant","variant","disabled","onClick","SceneIcon","reference"],"mappings":";;;;;;AAAA;AACA;AAcA,SAASA,oBAAoBC,KAAc,EAAA;AACvC,IAAA,MAAMC,SAAAA,GAAYD,KAAAA;AAClB,IAAA,OAAOC,SAAAA,KAAc,IAAA,IAAQ,OAAOA,SAAAA,KAAc,QAAA,IAAY,OAAOA,SAAAA,CAAUC,EAAE,KAAK,QAAA,IAAY,OAAOD,SAAAA,CAAUE,KAAK,KAAK,QAAA;AACjI;AAEA;;;;;;;;;AASC,IACM,SAASC,iBAAAA,CAAkB,EAAEC,OAAO,EAA4B,EAAA;AACnE,IAAA,MAAMC,QAAQC,KAAAA,CAAMC,OAAO,CAACH,OAAAA,CAAQI,UAAU,CAACH,KAAK,CAAA,GAAID,OAAAA,CAAQI,UAAU,CAACH,KAAK,CAACI,MAAM,CAACX,uBAAuB,EAAE;AACjH,IAAA,MAAMY,QAAAA,GAAWC,kCAAAA,EAAAA;AACjB,IAAA,MAAMC,KAAAA,GAAQ,OAAOR,OAAAA,CAAQI,UAAU,CAACI,KAAK,KAAK,QAAA,GAAWR,OAAAA,CAAQI,UAAU,CAACI,KAAK,GAAGC,SAAAA;AAExF,IAAA,qBACIC,cAAA,CAACC,KAAAA,EAAAA;AAAIC,QAAAA,eAAAA,EAAeZ,QAAQH,EAAE;QAAEgB,YAAAA,EAAYL,KAAAA;kBACvCP,KAAAA,CAAMa,GAAG,CAACC,CAAAA,IAAAA,GAAAA;AACP,YAAA,MAAMC,YAAAA,GAAeD,IAAAA,CAAKE,WAAW,EAAEC,MAAAA,IAAU,EAAA;AACjD,YAAA,MAAMC,WAAW,IAAMC,UAAAA,CAAWC,aAAa,CAAC,IAAIC,YAAY,uBAAA,EAAyB;oBAAEC,MAAAA,EAAQ;AAAEP,wBAAAA,YAAAA;AAAchB,wBAAAA,OAAAA;AAASe,wBAAAA;AAAK;AAAE,iBAAA,CAAA,CAAA;AACnI,YAAA,qBACIS,eAAA,CAACC,QAAAA,EAAAA;gBAEGC,IAAAA,EAAK,QAAA;AACLC,gBAAAA,iBAAAA,EAAiBZ,KAAKlB,EAAE;gBACxB+B,yBAAAA,EAAyBb,IAAAA,CAAKc,IAAI,EAAEC,OAAAA;gBACpCC,qBAAAA,EAAqBhB,IAAAA,CAAKc,IAAI,EAAEG,GAAAA;gBAChCC,yBAAAA,EAAyBlB,IAAAA,CAAKc,IAAI,EAAEK,OAAAA;AACpCC,gBAAAA,QAAAA,EAAUnB,YAAAA,KAAiB,EAAA;gBAC3BoB,OAAAA,EAASjB,QAAAA;;oBAERJ,IAAAA,CAAKc,IAAI,IAAIvB,QAAAA,iBAAWI,cAAA,CAAC2B,mBAAAA,EAAAA;AAAUC,wBAAAA,SAAAA,EAAWvB,KAAKc,IAAI;wBAAEvB,QAAAA,EAAUA;AAAe,qBAAA,CAAA,GAAA,IAAA;AAClFS,oBAAAA,IAAAA,CAAKjB;;AAVDiB,aAAAA,EAAAA,IAAAA,CAAKlB,EAAE,CAAA;AAaxB,QAAA,CAAA;;AAGZ;;"}
@@ -0,0 +1,21 @@
1
+ 'use strict';
2
+
3
+ var jsxRuntime = require('react/jsx-runtime');
4
+ var react = require('react');
5
+
6
+ const IconAdapterContext = /*#__PURE__*/ react.createContext(undefined);
7
+ /**
8
+ * Supplies the icon adapters every `SceneIcon` below it renders through.
9
+ */ const IconAdapterProvider = ({ registry, children })=>/*#__PURE__*/ jsxRuntime.jsx(IconAdapterContext.Provider, {
10
+ value: registry,
11
+ children: children
12
+ });
13
+ /**
14
+ * The icon adapters in scope, or `undefined` outside an {@link IconAdapterProvider}.
15
+ */ function useIconAdapters() {
16
+ return react.useContext(IconAdapterContext);
17
+ }
18
+
19
+ exports.IconAdapterProvider = IconAdapterProvider;
20
+ exports.useIconAdapters = useIconAdapters;
21
+ //# sourceMappingURL=IconAdapterContext.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IconAdapterContext.js","sources":["../../../icons/IconAdapterContext.tsx"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { ReactNode, createContext, useContext } from 'react';\nimport { IconAdapterRegistry } from './IconAdapterRegistry';\n\nconst IconAdapterContext = createContext<IconAdapterRegistry | undefined>(undefined);\n\n/**\n * Supplies the icon adapters every `SceneIcon` below it renders through.\n */\nexport const IconAdapterProvider = ({ registry, children }: { registry: IconAdapterRegistry; children?: ReactNode }) => (\n <IconAdapterContext.Provider value={registry}>{children}</IconAdapterContext.Provider>\n);\n\n/**\n * The icon adapters in scope, or `undefined` outside an {@link IconAdapterProvider}.\n */\nexport function useIconAdapters(): IconAdapterRegistry | undefined {\n return useContext(IconAdapterContext);\n}\n"],"names":["IconAdapterContext","createContext","undefined","IconAdapterProvider","registry","children","_jsx","Provider","value","useIconAdapters","useContext"],"mappings":";;;;;AAMA,MAAMA,mCAAqBC,mBAAAA,CAA+CC,SAAAA,CAAAA;AAE1E;;AAEC,IACM,MAAMC,mBAAAA,GAAsB,CAAC,EAAEC,QAAQ,EAAEC,QAAQ,EAA2D,iBAC/GC,cAAA,CAACN,kBAAAA,CAAmBO,QAAQ,EAAA;QAACC,KAAAA,EAAOJ,QAAAA;AAAWC,QAAAA,QAAAA,EAAAA;AACjD,KAAA;AAEF;;AAEC,IACM,SAASI,eAAAA,GAAAA;AACZ,IAAA,OAAOC,gBAAAA,CAAWV,kBAAAA,CAAAA;AACtB;;;"}
@@ -0,0 +1,45 @@
1
+ 'use strict';
2
+
3
+ // Copyright (c) Cratis. All rights reserved.
4
+ // Licensed under the MIT license. See LICENSE file in the project root for full license information.
5
+ /**
6
+ * The icon adapters a renderer has, one per library. Registering is explicit and never replaces: two
7
+ * adapters for one library would mean an icon renders differently depending on registration order, which
8
+ * is the silent swapping the library-qualified reference exists to prevent.
9
+ */ class IconAdapterRegistry {
10
+ #adapters = new Map();
11
+ /**
12
+ * Adds an adapter.
13
+ *
14
+ * @throws Error when an adapter for the same library is already registered.
15
+ */ register(adapter) {
16
+ if (this.#adapters.has(adapter.library)) {
17
+ throw new Error(`An icon adapter for the library '${adapter.library}' is already registered`);
18
+ }
19
+ this.#adapters.set(adapter.library, adapter);
20
+ return this;
21
+ }
22
+ /**
23
+ * The adapter for a library, or `undefined` when this renderer has none.
24
+ */ get(library) {
25
+ return this.#adapters.get(library);
26
+ }
27
+ /**
28
+ * The libraries this registry can render.
29
+ */ get libraries() {
30
+ return [
31
+ ...this.#adapters.keys()
32
+ ];
33
+ }
34
+ }
35
+ /**
36
+ * Creates a registry holding the given adapters.
37
+ */ function createIconAdapterRegistry(adapters = []) {
38
+ const registry = new IconAdapterRegistry();
39
+ adapters.forEach((adapter)=>registry.register(adapter));
40
+ return registry;
41
+ }
42
+
43
+ exports.IconAdapterRegistry = IconAdapterRegistry;
44
+ exports.createIconAdapterRegistry = createIconAdapterRegistry;
45
+ //# sourceMappingURL=IconAdapterRegistry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IconAdapterRegistry.js","sources":["../../../icons/IconAdapterRegistry.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { IconAdapter } from './IconAdapter';\n\n/**\n * The icon adapters a renderer has, one per library. Registering is explicit and never replaces: two\n * adapters for one library would mean an icon renders differently depending on registration order, which\n * is the silent swapping the library-qualified reference exists to prevent.\n */\nexport class IconAdapterRegistry {\n readonly #adapters = new Map<string, IconAdapter>();\n\n /**\n * Adds an adapter.\n *\n * @throws Error when an adapter for the same library is already registered.\n */\n register(adapter: IconAdapter): this {\n if (this.#adapters.has(adapter.library)) {\n throw new Error(`An icon adapter for the library '${adapter.library}' is already registered`);\n }\n\n this.#adapters.set(adapter.library, adapter);\n return this;\n }\n\n /**\n * The adapter for a library, or `undefined` when this renderer has none.\n */\n get(library: string): IconAdapter | undefined {\n return this.#adapters.get(library);\n }\n\n /**\n * The libraries this registry can render.\n */\n get libraries(): string[] {\n return [...this.#adapters.keys()];\n }\n}\n\n/**\n * Creates a registry holding the given adapters.\n */\nexport function createIconAdapterRegistry(adapters: IconAdapter[] = []): IconAdapterRegistry {\n const registry = new IconAdapterRegistry();\n adapters.forEach((adapter) => registry.register(adapter));\n return registry;\n}\n"],"names":["IconAdapterRegistry","Map","register","adapter","has","library","Error","set","get","libraries","keys","createIconAdapterRegistry","adapters","registry","forEach"],"mappings":";;AAAA;AACA;AAIA;;;;AAIC,IACM,MAAMA,mBAAAA,CAAAA;IACA,SAAS,GAAG,IAAIC,GAAAA,EAAAA;AAEzB;;;;QAKAC,QAAAA,CAASC,OAAoB,EAAQ;QACjC,IAAI,IAAI,CAAC,SAAS,CAACC,GAAG,CAACD,OAAAA,CAAQE,OAAO,CAAA,EAAG;YACrC,MAAM,IAAIC,MAAM,CAAC,iCAAiC,EAAEH,OAAAA,CAAQE,OAAO,CAAC,uBAAuB,CAAC,CAAA;AAChG,QAAA;QAEA,IAAI,CAAC,SAAS,CAACE,GAAG,CAACJ,OAAAA,CAAQE,OAAO,EAAEF,OAAAA,CAAAA;AACpC,QAAA,OAAO,IAAI;AACf,IAAA;AAEA;;QAGAK,GAAAA,CAAIH,OAAe,EAA2B;AAC1C,QAAA,OAAO,IAAI,CAAC,SAAS,CAACG,GAAG,CAACH,OAAAA,CAAAA;AAC9B,IAAA;AAEA;;AAEC,QACD,IAAII,SAAAA,GAAsB;QACtB,OAAO;AAAI,YAAA,GAAA,IAAI,CAAC,SAAS,CAACC,IAAI;AAAG,SAAA;AACrC,IAAA;AACJ;AAEA;;AAEC,IACM,SAASC,yBAAAA,CAA0BC,QAAAA,GAA0B,EAAE,EAAA;AAClE,IAAA,MAAMC,WAAW,IAAIb,mBAAAA,EAAAA;AACrBY,IAAAA,QAAAA,CAASE,OAAO,CAAC,CAACX,OAAAA,GAAYU,QAAAA,CAASX,QAAQ,CAACC,OAAAA,CAAAA,CAAAA;IAChD,OAAOU,QAAAA;AACX;;;"}
@@ -0,0 +1,42 @@
1
+ 'use strict';
2
+
3
+ var jsxRuntime = require('react/jsx-runtime');
4
+ var IconAdapterContext = require('./IconAdapterContext.js');
5
+ var useIconGlyph = require('./useIconGlyph.js');
6
+
7
+ // Copyright (c) Cratis. All rights reserved.
8
+ // Licensed under the MIT license. See LICENSE file in the project root for full license information.
9
+ /**
10
+ * Draws a renderer-neutral {@link IconReference} through the adapter registered for its library, honoring
11
+ * size, color and accessible label. The reference is all that is persisted; this is where it becomes pixels.
12
+ */ const SceneIcon = ({ reference, adapters, size = '1em', color = 'currentColor', label, className, fallback })=>{
13
+ const inScope = IconAdapterContext.useIconAdapters();
14
+ const state = useIconGlyph.useIconGlyph(reference, adapters ?? inScope);
15
+ const Glyph = state.status === 'ready' ? state.glyph : undefined;
16
+ return /*#__PURE__*/ jsxRuntime.jsx("span", {
17
+ className: className,
18
+ role: label ? 'img' : undefined,
19
+ "aria-label": label,
20
+ "aria-hidden": label ? undefined : true,
21
+ "data-icon-library": reference.library,
22
+ "data-icon-key": reference.key,
23
+ "data-icon-variant": reference.variant,
24
+ "data-icon-state": state.status,
25
+ style: {
26
+ display: 'inline-flex',
27
+ alignItems: 'center',
28
+ justifyContent: 'center',
29
+ width: size,
30
+ height: size,
31
+ color,
32
+ flexShrink: 0
33
+ },
34
+ children: Glyph ? /*#__PURE__*/ jsxRuntime.jsx(Glyph, {
35
+ size: size,
36
+ color: color
37
+ }) : state.status === 'unavailable' ? fallback : null
38
+ });
39
+ };
40
+
41
+ exports.SceneIcon = SceneIcon;
42
+ //# sourceMappingURL=SceneIcon.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SceneIcon.js","sources":["../../../icons/SceneIcon.tsx"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { ReactNode } from 'react';\nimport { IconReference } from '@cratis/scene.model';\nimport { IconAdapterRegistry } from './IconAdapterRegistry';\nimport { useIconAdapters } from './IconAdapterContext';\nimport { useIconGlyph } from './useIconGlyph';\n\nexport interface SceneIconProps {\n /**\n * The icon to draw.\n */\n reference: IconReference;\n\n /**\n * The adapters to render through. Defaults to the ones an `IconAdapterProvider` supplies.\n */\n adapters?: IconAdapterRegistry;\n\n /**\n * The width and height of the icon: a number of pixels or any CSS length. Defaults to `1em`, so an\n * icon scales with the text it sits in.\n */\n size?: number | string;\n\n /**\n * The color to draw in. Defaults to `currentColor`.\n */\n color?: string;\n\n /**\n * The accessible name. With a label the icon is announced as an image; without one it is decorative\n * and hidden from assistive technology - an icon next to its own text label should not be read twice.\n */\n label?: string;\n\n /**\n * An optional class for the box the icon sits in.\n */\n className?: string;\n\n /**\n * What to show when the icon cannot be drawn - no adapter, no such icon, a failed load. Nothing by\n * default; the box keeps its size so layout does not shift.\n */\n fallback?: ReactNode;\n}\n\n/**\n * Draws a renderer-neutral {@link IconReference} through the adapter registered for its library, honoring\n * size, color and accessible label. The reference is all that is persisted; this is where it becomes pixels.\n */\nexport const SceneIcon = ({ reference, adapters, size = '1em', color = 'currentColor', label, className, fallback }: SceneIconProps) => {\n const inScope = useIconAdapters();\n const state = useIconGlyph(reference, adapters ?? inScope);\n const Glyph = state.status === 'ready' ? state.glyph : undefined;\n\n return (\n <span\n className={className}\n role={label ? 'img' : undefined}\n aria-label={label}\n aria-hidden={label ? undefined : true}\n data-icon-library={reference.library}\n data-icon-key={reference.key}\n data-icon-variant={reference.variant}\n data-icon-state={state.status}\n style={{ display: 'inline-flex', alignItems: 'center', justifyContent: 'center', width: size, height: size, color, flexShrink: 0 }}>\n {Glyph ? <Glyph size={size} color={color} /> : state.status === 'unavailable' ? fallback : null}\n </span>\n );\n};\n"],"names":["SceneIcon","reference","adapters","size","color","label","className","fallback","inScope","useIconAdapters","state","useIconGlyph","Glyph","status","glyph","undefined","_jsx","span","role","aria-label","aria-hidden","data-icon-library","library","data-icon-key","key","data-icon-variant","variant","data-icon-state","style","display","alignItems","justifyContent","width","height","flexShrink"],"mappings":";;;;;;AAAA;AACA;AAgDA;;;UAIaA,SAAAA,GAAY,CAAC,EAAEC,SAAS,EAAEC,QAAQ,EAAEC,IAAAA,GAAO,KAAK,EAAEC,KAAAA,GAAQ,cAAc,EAAEC,KAAK,EAAEC,SAAS,EAAEC,QAAQ,EAAkB,GAAA;AAC/H,IAAA,MAAMC,OAAAA,GAAUC,kCAAAA,EAAAA;IAChB,MAAMC,KAAAA,GAAQC,yBAAAA,CAAaV,SAAAA,EAAWC,QAAAA,IAAYM,OAAAA,CAAAA;AAClD,IAAA,MAAMI,QAAQF,KAAAA,CAAMG,MAAM,KAAK,OAAA,GAAUH,KAAAA,CAAMI,KAAK,GAAGC,SAAAA;AAEvD,IAAA,qBACIC,cAAA,CAACC,MAAAA,EAAAA;QACGX,SAAAA,EAAWA,SAAAA;AACXY,QAAAA,IAAAA,EAAMb,QAAQ,KAAA,GAAQU,SAAAA;QACtBI,YAAAA,EAAYd,KAAAA;AACZe,QAAAA,aAAAA,EAAaf,QAAQU,SAAAA,GAAY,IAAA;AACjCM,QAAAA,mBAAAA,EAAmBpB,UAAUqB,OAAO;AACpCC,QAAAA,eAAAA,EAAetB,UAAUuB,GAAG;AAC5BC,QAAAA,mBAAAA,EAAmBxB,UAAUyB,OAAO;AACpCC,QAAAA,iBAAAA,EAAiBjB,MAAMG,MAAM;QAC7Be,KAAAA,EAAO;YAAEC,OAAAA,EAAS,aAAA;YAAeC,UAAAA,EAAY,QAAA;YAAUC,cAAAA,EAAgB,QAAA;YAAUC,KAAAA,EAAO7B,IAAAA;YAAM8B,MAAAA,EAAQ9B,IAAAA;AAAMC,YAAAA,KAAAA;YAAO8B,UAAAA,EAAY;AAAE,SAAA;AAChItB,QAAAA,QAAAA,EAAAA,KAAAA,iBAAQI,cAAA,CAACJ,KAAAA,EAAAA;YAAMT,IAAAA,EAAMA,IAAAA;YAAMC,KAAAA,EAAOA;aAAYM,KAAAA,CAAMG,MAAM,KAAK,aAAA,GAAgBN,QAAAA,GAAW;;AAGvG;;"}
@@ -0,0 +1,86 @@
1
+ 'use strict';
2
+
3
+ var react = require('react');
4
+
5
+ // Copyright (c) Cratis. All rights reserved.
6
+ // Licensed under the MIT license. See LICENSE file in the project root for full license information.
7
+ const loads = new WeakMap();
8
+ function keyOf(reference) {
9
+ return JSON.stringify([
10
+ reference.key,
11
+ reference.variant ?? null
12
+ ]);
13
+ }
14
+ /**
15
+ * One load per adapter and icon, shared between every place the icon is drawn; a failed load is
16
+ * forgotten so the next render can try again.
17
+ */ function load(adapter, reference) {
18
+ let perAdapter = loads.get(adapter);
19
+ if (!perAdapter) {
20
+ perAdapter = new Map();
21
+ loads.set(adapter, perAdapter);
22
+ }
23
+ const key = keyOf(reference);
24
+ let pending = perAdapter.get(key);
25
+ if (!pending) {
26
+ pending = Promise.resolve().then(()=>adapter.loadGlyph(reference));
27
+ perAdapter.set(key, pending);
28
+ pending.catch(()=>perAdapter.delete(key));
29
+ }
30
+ return pending;
31
+ }
32
+ /**
33
+ * Loads the artwork for a reference through the adapter registered for its library. An absent registry,
34
+ * a library with no adapter, an icon the library lacks and a failed load are all `unavailable`, each with
35
+ * its reason - never a different icon.
36
+ */ function useIconGlyph(reference, adapters) {
37
+ const [state, setState] = react.useState({
38
+ status: 'loading'
39
+ });
40
+ const { library, key, variant } = reference;
41
+ react.useEffect(()=>{
42
+ let isCurrent = true;
43
+ const adapter = adapters?.get(library);
44
+ if (!adapter) {
45
+ setState({
46
+ status: 'unavailable',
47
+ reason: `No icon adapter is registered for the library '${library}'`
48
+ });
49
+ return;
50
+ }
51
+ setState({
52
+ status: 'loading'
53
+ });
54
+ load(adapter, {
55
+ library,
56
+ key,
57
+ variant
58
+ }).then((glyph)=>{
59
+ if (!isCurrent) return;
60
+ setState(glyph ? {
61
+ status: 'ready',
62
+ glyph
63
+ } : {
64
+ status: 'unavailable',
65
+ reason: `The library '${library}' has no icon '${key}'`
66
+ });
67
+ }, (error)=>{
68
+ if (isCurrent) setState({
69
+ status: 'unavailable',
70
+ reason: error instanceof Error ? error.message : String(error)
71
+ });
72
+ });
73
+ return ()=>{
74
+ isCurrent = false;
75
+ };
76
+ }, [
77
+ adapters,
78
+ library,
79
+ key,
80
+ variant
81
+ ]);
82
+ return state;
83
+ }
84
+
85
+ exports.useIconGlyph = useIconGlyph;
86
+ //# sourceMappingURL=useIconGlyph.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useIconGlyph.js","sources":["../../../icons/useIconGlyph.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { useEffect, useState } from 'react';\nimport { IconReference } from '@cratis/scene.model';\nimport { IconAdapter, IconGlyph } from './IconAdapter';\nimport { IconAdapterRegistry } from './IconAdapterRegistry';\n\n/**\n * Where loading one icon's artwork stands.\n */\nexport type IconGlyphState =\n | { status: 'loading' }\n | { status: 'ready'; glyph: IconGlyph }\n | { status: 'unavailable'; reason: string };\n\nconst loads = new WeakMap<IconAdapter, Map<string, Promise<IconGlyph | undefined>>>();\n\nfunction keyOf(reference: IconReference): string {\n return JSON.stringify([reference.key, reference.variant ?? null]);\n}\n\n/**\n * One load per adapter and icon, shared between every place the icon is drawn; a failed load is\n * forgotten so the next render can try again.\n */\nfunction load(adapter: IconAdapter, reference: IconReference): Promise<IconGlyph | undefined> {\n let perAdapter = loads.get(adapter);\n if (!perAdapter) {\n perAdapter = new Map();\n loads.set(adapter, perAdapter);\n }\n\n const key = keyOf(reference);\n let pending = perAdapter.get(key);\n if (!pending) {\n pending = Promise.resolve().then(() => adapter.loadGlyph(reference));\n perAdapter.set(key, pending);\n pending.catch(() => perAdapter.delete(key));\n }\n\n return pending;\n}\n\n/**\n * Loads the artwork for a reference through the adapter registered for its library. An absent registry,\n * a library with no adapter, an icon the library lacks and a failed load are all `unavailable`, each with\n * its reason - never a different icon.\n */\nexport function useIconGlyph(reference: IconReference, adapters: IconAdapterRegistry | undefined): IconGlyphState {\n const [state, setState] = useState<IconGlyphState>({ status: 'loading' });\n const { library, key, variant } = reference;\n\n useEffect(() => {\n let isCurrent = true;\n const adapter = adapters?.get(library);\n if (!adapter) {\n setState({ status: 'unavailable', reason: `No icon adapter is registered for the library '${library}'` });\n return;\n }\n\n setState({ status: 'loading' });\n load(adapter, { library, key, variant }).then(\n (glyph) => {\n if (!isCurrent) return;\n setState(glyph ? { status: 'ready', glyph } : { status: 'unavailable', reason: `The library '${library}' has no icon '${key}'` });\n },\n (error: unknown) => {\n if (isCurrent) setState({ status: 'unavailable', reason: error instanceof Error ? error.message : String(error) });\n }\n );\n\n return () => {\n isCurrent = false;\n };\n }, [adapters, library, key, variant]);\n\n return state;\n}\n"],"names":["loads","WeakMap","keyOf","reference","JSON","stringify","key","variant","load","adapter","perAdapter","get","Map","set","pending","Promise","resolve","then","loadGlyph","catch","delete","useIconGlyph","adapters","state","setState","useState","status","library","useEffect","isCurrent","reason","glyph","error","Error","message","String"],"mappings":"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"}
package/dist/cjs/index.js CHANGED
@@ -14,6 +14,10 @@ var coreComponents = require('./core/coreComponents.js');
14
14
  var corePackage = require('./core/corePackage.js');
15
15
  var NavBar = require('./NavBar/NavBar.js');
16
16
  var extractNavigationItem = require('./NavBar/extractNavigationItem.js');
17
+ var IconAdapterRegistry = require('./icons/IconAdapterRegistry.js');
18
+ var IconAdapterContext = require('./icons/IconAdapterContext.js');
19
+ var useIconGlyph = require('./icons/useIconGlyph.js');
20
+ var SceneIcon = require('./icons/SceneIcon.js');
17
21
  var ScenePackageBundle = require('./packages/ScenePackageBundle.js');
18
22
  var themeTokens = require('./theme/themeTokens.js');
19
23
  var SceneThemeProvider = require('./theme/SceneThemeProvider.js');
@@ -52,7 +56,14 @@ exports.corePackage = corePackage.corePackage;
52
56
  exports.corePackageManifest = corePackage.corePackageManifest;
53
57
  exports.NavBar = NavBar.NavBar;
54
58
  exports.extractNavigationItem = extractNavigationItem.extractNavigationItem;
59
+ exports.IconAdapterRegistry = IconAdapterRegistry.IconAdapterRegistry;
60
+ exports.createIconAdapterRegistry = IconAdapterRegistry.createIconAdapterRegistry;
61
+ exports.IconAdapterProvider = IconAdapterContext.IconAdapterProvider;
62
+ exports.useIconAdapters = IconAdapterContext.useIconAdapters;
63
+ exports.useIconGlyph = useIconGlyph.useIconGlyph;
64
+ exports.SceneIcon = SceneIcon.SceneIcon;
55
65
  exports.componentRegistryKey = ScenePackageBundle.componentRegistryKey;
66
+ exports.mergeIconAdapters = ScenePackageBundle.mergeIconAdapters;
56
67
  exports.mergePackageRegistries = ScenePackageBundle.mergePackageRegistries;
57
68
  exports.validatePackageBundle = ScenePackageBundle.validatePackageBundle;
58
69
  exports.applyThemeTokens = themeTokens.applyThemeTokens;
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -1,6 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  var scene_model = require('@cratis/scene.model');
4
+ var IconAdapterRegistry = require('../icons/IconAdapterRegistry.js');
4
5
 
5
6
  // Copyright (c) Cratis. All rights reserved.
6
7
  // Licensed under the MIT license. See LICENSE file in the project root for full license information.
@@ -62,9 +63,39 @@ var scene_model = require('@cratis/scene.model');
62
63
  problems.push(`declares the theme '${name}' but provides no definition for it`);
63
64
  }
64
65
  }
66
+ problems.push(...validateIconLibrary(bundle));
65
67
  problems.push(...validateDescriptors(bundle));
66
68
  return problems;
67
69
  }
70
+ function validateIconLibrary(bundle) {
71
+ const problems = [];
72
+ const { manifest, iconLibrary } = bundle;
73
+ const declaresIconLibrary = manifest.kind === scene_model.PackageKind.IconLibrary || manifest.iconLibrary !== undefined;
74
+ if (manifest.kind === scene_model.PackageKind.IconLibrary && !manifest.iconLibrary) {
75
+ problems.push('is an icon library but declares no iconLibrary metadata');
76
+ }
77
+ if (manifest.kind !== scene_model.PackageKind.IconLibrary && manifest.iconLibrary) {
78
+ problems.push('declares iconLibrary metadata but is not of kind IconLibrary');
79
+ }
80
+ if (declaresIconLibrary && !iconLibrary) {
81
+ problems.push('declares an icon library but the bundle provides no catalog or adapter for it');
82
+ }
83
+ if (!declaresIconLibrary && iconLibrary) {
84
+ problems.push('provides an icon catalog and adapter, which the manifest does not declare');
85
+ }
86
+ if (iconLibrary) {
87
+ if (iconLibrary.catalog.library !== manifest.name) {
88
+ problems.push(`provides an icon catalog for '${iconLibrary.catalog.library}' instead of '${manifest.name}'`);
89
+ }
90
+ if (iconLibrary.adapter.library !== manifest.name) {
91
+ problems.push(`provides an icon adapter for '${iconLibrary.adapter.library}' instead of '${manifest.name}'`);
92
+ }
93
+ if (manifest.iconLibrary && !manifest.iconLibrary.renderers.includes('react')) {
94
+ problems.push("provides a React icon adapter but does not list 'react' among its icon renderers");
95
+ }
96
+ }
97
+ return problems;
98
+ }
68
99
  function validateDescriptors(bundle) {
69
100
  const problems = [];
70
101
  const declared = new Set(bundle.manifest.components.map((name)=>componentRegistryKey(bundle.manifest.name, name)));
@@ -101,8 +132,18 @@ function validateDescriptors(bundle) {
101
132
  */ function mergePackageRegistries(bundles) {
102
133
  return Object.assign({}, ...bundles.map((bundle)=>bundle.components));
103
134
  }
135
+ /**
136
+ * Collects the icon adapters of several bundles into the registry `SceneIcon` renders through.
137
+ *
138
+ * @throws Error when two bundles provide an adapter for the same library.
139
+ */ function mergeIconAdapters(bundles) {
140
+ return IconAdapterRegistry.createIconAdapterRegistry(bundles.flatMap((bundle)=>bundle.iconLibrary ? [
141
+ bundle.iconLibrary.adapter
142
+ ] : []));
143
+ }
104
144
 
105
145
  exports.componentRegistryKey = componentRegistryKey;
146
+ exports.mergeIconAdapters = mergeIconAdapters;
106
147
  exports.mergePackageRegistries = mergePackageRegistries;
107
148
  exports.validatePackageBundle = validatePackageBundle;
108
149
  //# sourceMappingURL=ScenePackageBundle.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ScenePackageBundle.js","sources":["../../../packages/ScenePackageBundle.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { ComponentDescriptor, DialogTemplate, Layout, PropertyValueType, ScenePackage, Screen, ScreenTemplate, Theme } from '@cratis/scene.model';\nimport { ComponentRegistry } from '../renderer';\n\n/**\n * What a package actually ships to a React renderer, as opposed to what it *declares*.\n *\n * `ScenePackage` is the declaration — a name, a kind, dependencies, and the names of what it\n * contributes. It is deliberately platform-agnostic and lives in `Scene.Model`, because Stage's build and\n * Studio's design-time queries both read it without ever loading a component. A bundle is the other half:\n * the real React components, layouts, screens and themes behind those names, which only a renderer needs.\n *\n * A package publishes exactly one bundle, as a named export following its own name —\n * `primeReactPackage`, `cratisComponentsPackage`, `corePackage`. A host loads it from the module the\n * declaration's `ScenePackage.module` names.\n */\nexport interface ScenePackageBundle {\n /**\n * The package's own declaration. Its `components`, `layouts` and `themes` name lists must agree with\n * what this bundle actually provides — {@link validatePackageBundle} is what proves they do.\n */\n manifest: ScenePackage;\n\n /**\n * The components this package provides, keyed by {@link componentRegistryKey}.\n */\n components: ComponentRegistry;\n\n /**\n * The application shells this package provides, if any. Only a blueprint has these.\n */\n layouts?: Layout[];\n\n /**\n * The screen templates this package provides — the shapes that go inside a layout, each declaring\n * which of its parent's slots it fills.\n */\n screenTemplates?: ScreenTemplate[];\n\n /**\n * The dialog templates this package provides.\n */\n dialogTemplates?: DialogTemplate[];\n\n /**\n * Sample screens this package ships — a layout package's gallery, so a preview has real content to\n * put through the real engine rather than a mockup.\n */\n screens?: Screen[];\n\n /**\n * What can be edited on this package's components - one {@link ComponentDescriptor} per component that is\n * editable at design time. They are data, so Studio reads them without rendering anything, and they travel with\n * the components they describe rather than in a registry of their own. {@link validatePackageBundle} checks\n * that every descriptor names a component the manifest declares.\n */\n descriptors?: ComponentDescriptor[];\n\n /**\n * The themes this package ships, if any.\n */\n themes?: Theme[];\n}\n\n/**\n * The key a component is registered and looked up under: the package that provides it, then the bare name\n * a screen refers to it by.\n *\n * A screen writes a bare name (`button`) or a package-qualified one (`PrimeReact.button`);\n * `resolveComponentName` turns either into a `{ name, package }` pair, and this turns that pair into the\n * registry key. Nothing should build this string by hand — the separator is an implementation detail of\n * the registry, deliberately not the `.` used for qualification in a screen, so a package name containing\n * dots stays unambiguous.\n */\nexport function componentRegistryKey(packageName: string, componentName: string): string {\n return `${packageName}:${componentName}`;\n}\n\n/**\n * Checks that a bundle provides everything its manifest declares, and declares everything it provides, and that\n * every descriptor it ships is for a component it declares and is well formed.\n *\n * A manifest that promises a component the bundle does not register renders as `UnresolvedComponent` at\n * runtime — a blank box, far from where the mistake was made. A component registered but not declared is\n * invisible to `resolveComponentName`, so a screen can never name it. Both are silent failures, which is\n * why every package's specs run this.\n */\nexport function validatePackageBundle(bundle: ScenePackageBundle): string[] {\n const problems: string[] = [];\n const { manifest } = bundle;\n\n for (const name of manifest.components) {\n if (!(componentRegistryKey(manifest.name, name) in bundle.components)) {\n problems.push(`declares the component '${name}' but registers no implementation for it`);\n }\n }\n\n const declared = new Set(manifest.components.map((name) => componentRegistryKey(manifest.name, name)));\n for (const key of Object.keys(bundle.components)) {\n if (!declared.has(key)) {\n problems.push(`registers '${key}', which the manifest does not declare`);\n }\n }\n\n const providedLayouts = new Set((bundle.layouts ?? []).map((layout) => layout.name));\n for (const name of manifest.layouts) {\n if (!providedLayouts.has(name)) {\n problems.push(`declares the layout '${name}' but provides no definition for it`);\n }\n }\n\n const providedScreenTemplates = new Set((bundle.screenTemplates ?? []).map((template) => template.name));\n for (const name of manifest.screenTemplates) {\n if (!providedScreenTemplates.has(name)) {\n problems.push(`declares the screen template '${name}' but provides no definition for it`);\n }\n }\n\n const providedDialogTemplates = new Set((bundle.dialogTemplates ?? []).map((template) => template.name));\n for (const name of manifest.dialogTemplates) {\n if (!providedDialogTemplates.has(name)) {\n problems.push(`declares the dialog template '${name}' but provides no definition for it`);\n }\n }\n\n const providedThemes = new Set((bundle.themes ?? []).map((theme) => theme.name));\n for (const name of manifest.themes) {\n if (!providedThemes.has(name)) {\n problems.push(`declares the theme '${name}' but provides no definition for it`);\n }\n }\n\n problems.push(...validateDescriptors(bundle));\n return problems;\n}\n\nfunction validateDescriptors(bundle: ScenePackageBundle): string[] {\n const problems: string[] = [];\n const declared = new Set(bundle.manifest.components.map((name) => componentRegistryKey(bundle.manifest.name, name)));\n const described = new Set<string>();\n\n for (const descriptor of bundle.descriptors ?? []) {\n if (!declared.has(descriptor.component)) {\n problems.push(`describes '${descriptor.component}', which the manifest does not declare as a component`);\n }\n\n if (described.has(descriptor.component)) {\n problems.push(`describes '${descriptor.component}' more than once`);\n }\n\n described.add(descriptor.component);\n\n const paths = new Set<string>();\n for (const property of descriptor.properties) {\n if (paths.has(property.path)) {\n problems.push(`'${descriptor.component}' describes the property '${property.path}' more than once`);\n }\n\n paths.add(property.path);\n\n if (property.valueType === PropertyValueType.Collection && property.item === undefined) {\n problems.push(`'${descriptor.component}' describes the collection '${property.path}' without describing its items`);\n }\n\n if (property.valueType === PropertyValueType.Enum && (property.choices ?? []).length === 0) {\n problems.push(`'${descriptor.component}' describes the enum '${property.path}' without choices`);\n }\n }\n }\n\n return problems;\n}\n\n/**\n * Merges the component registries of several bundles into the single registry a renderer consumes.\n *\n * Keys carry their package name, so nothing collides and merge order does not matter — which package wins\n * a *bare* name is decided earlier, by `resolveComponentName` walking the profile's priority order.\n */\nexport function mergePackageRegistries(bundles: ScenePackageBundle[]): ComponentRegistry {\n return Object.assign({}, ...bundles.map((bundle) => bundle.components)) as ComponentRegistry;\n}\n"],"names":["componentRegistryKey","packageName","componentName","validatePackageBundle","bundle","problems","manifest","name","components","push","declared","Set","map","key","Object","keys","has","providedLayouts","layouts","layout","providedScreenTemplates","screenTemplates","template","providedDialogTemplates","dialogTemplates","providedThemes","themes","theme","validateDescriptors","described","descriptor","descriptors","component","add","paths","property","properties","path","valueType","PropertyValueType","Collection","item","undefined","Enum","choices","length","mergePackageRegistries","bundles","assign"],"mappings":"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"}
1
+ {"version":3,"file":"ScenePackageBundle.js","sources":["../../../packages/ScenePackageBundle.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { ComponentDescriptor, DialogTemplate, Layout, PackageKind, PropertyValueType, ScenePackage, Screen, ScreenTemplate, Theme } from '@cratis/scene.model';\nimport { IconAdapterRegistry, createIconAdapterRegistry } from '../icons/IconAdapterRegistry';\nimport { IconLibraryBundle } from '../icons/IconLibraryBundle';\nimport { ComponentRegistry } from '../renderer';\n\n/**\n * What a package actually ships to a React renderer, as opposed to what it *declares*.\n *\n * `ScenePackage` is the declaration — a name, a kind, dependencies, and the names of what it\n * contributes. It is deliberately platform-agnostic and lives in `Scene.Model`, because Stage's build and\n * Studio's design-time queries both read it without ever loading a component. A bundle is the other half:\n * the real React components, layouts, screens and themes behind those names, which only a renderer needs.\n *\n * A package publishes exactly one bundle, as a named export following its own name —\n * `primeReactPackage`, `cratisComponentsPackage`, `corePackage`. A host loads it from the module the\n * declaration's `ScenePackage.module` names.\n */\nexport interface ScenePackageBundle {\n /**\n * The package's own declaration. Its `components`, `layouts` and `themes` name lists must agree with\n * what this bundle actually provides — {@link validatePackageBundle} is what proves they do.\n */\n manifest: ScenePackage;\n\n /**\n * The components this package provides, keyed by {@link componentRegistryKey}.\n */\n components: ComponentRegistry;\n\n /**\n * The application shells this package provides, if any. Only a blueprint has these.\n */\n layouts?: Layout[];\n\n /**\n * The screen templates this package provides — the shapes that go inside a layout, each declaring\n * which of its parent's slots it fills.\n */\n screenTemplates?: ScreenTemplate[];\n\n /**\n * The dialog templates this package provides.\n */\n dialogTemplates?: DialogTemplate[];\n\n /**\n * Sample screens this package ships — a layout package's gallery, so a preview has real content to\n * put through the real engine rather than a mockup.\n */\n screens?: Screen[];\n\n /**\n * What can be edited on this package's components - one {@link ComponentDescriptor} per component that is\n * editable at design time. They are data, so Studio reads them without rendering anything, and they travel with\n * the components they describe rather than in a registry of their own. {@link validatePackageBundle} checks\n * that every descriptor names a component the manifest declares.\n */\n descriptors?: ComponentDescriptor[];\n\n /**\n * The themes this package ships, if any.\n */\n themes?: Theme[];\n\n /**\n * The icon catalog and renderer adapter of an icon-library package. Present exactly when the\n * manifest declares an icon library.\n */\n iconLibrary?: IconLibraryBundle;\n}\n\n/**\n * The key a component is registered and looked up under: the package that provides it, then the bare name\n * a screen refers to it by.\n *\n * A screen writes a bare name (`button`) or a package-qualified one (`PrimeReact.button`);\n * `resolveComponentName` turns either into a `{ name, package }` pair, and this turns that pair into the\n * registry key. Nothing should build this string by hand — the separator is an implementation detail of\n * the registry, deliberately not the `.` used for qualification in a screen, so a package name containing\n * dots stays unambiguous.\n */\nexport function componentRegistryKey(packageName: string, componentName: string): string {\n return `${packageName}:${componentName}`;\n}\n\n/**\n * Checks that a bundle provides everything its manifest declares, and declares everything it provides, and that\n * every descriptor it ships is for a component it declares and is well formed.\n *\n * A manifest that promises a component the bundle does not register renders as `UnresolvedComponent` at\n * runtime — a blank box, far from where the mistake was made. A component registered but not declared is\n * invisible to `resolveComponentName`, so a screen can never name it. Both are silent failures, which is\n * why every package's specs run this.\n */\nexport function validatePackageBundle(bundle: ScenePackageBundle): string[] {\n const problems: string[] = [];\n const { manifest } = bundle;\n\n for (const name of manifest.components) {\n if (!(componentRegistryKey(manifest.name, name) in bundle.components)) {\n problems.push(`declares the component '${name}' but registers no implementation for it`);\n }\n }\n\n const declared = new Set(manifest.components.map((name) => componentRegistryKey(manifest.name, name)));\n for (const key of Object.keys(bundle.components)) {\n if (!declared.has(key)) {\n problems.push(`registers '${key}', which the manifest does not declare`);\n }\n }\n\n const providedLayouts = new Set((bundle.layouts ?? []).map((layout) => layout.name));\n for (const name of manifest.layouts) {\n if (!providedLayouts.has(name)) {\n problems.push(`declares the layout '${name}' but provides no definition for it`);\n }\n }\n\n const providedScreenTemplates = new Set((bundle.screenTemplates ?? []).map((template) => template.name));\n for (const name of manifest.screenTemplates) {\n if (!providedScreenTemplates.has(name)) {\n problems.push(`declares the screen template '${name}' but provides no definition for it`);\n }\n }\n\n const providedDialogTemplates = new Set((bundle.dialogTemplates ?? []).map((template) => template.name));\n for (const name of manifest.dialogTemplates) {\n if (!providedDialogTemplates.has(name)) {\n problems.push(`declares the dialog template '${name}' but provides no definition for it`);\n }\n }\n\n const providedThemes = new Set((bundle.themes ?? []).map((theme) => theme.name));\n for (const name of manifest.themes) {\n if (!providedThemes.has(name)) {\n problems.push(`declares the theme '${name}' but provides no definition for it`);\n }\n }\n\n problems.push(...validateIconLibrary(bundle));\n problems.push(...validateDescriptors(bundle));\n\n return problems;\n}\n\nfunction validateIconLibrary(bundle: ScenePackageBundle): string[] {\n const problems: string[] = [];\n const { manifest, iconLibrary } = bundle;\n const declaresIconLibrary = manifest.kind === PackageKind.IconLibrary || manifest.iconLibrary !== undefined;\n\n if (manifest.kind === PackageKind.IconLibrary && !manifest.iconLibrary) {\n problems.push('is an icon library but declares no iconLibrary metadata');\n }\n\n if (manifest.kind !== PackageKind.IconLibrary && manifest.iconLibrary) {\n problems.push('declares iconLibrary metadata but is not of kind IconLibrary');\n }\n\n if (declaresIconLibrary && !iconLibrary) {\n problems.push('declares an icon library but the bundle provides no catalog or adapter for it');\n }\n\n if (!declaresIconLibrary && iconLibrary) {\n problems.push('provides an icon catalog and adapter, which the manifest does not declare');\n }\n\n if (iconLibrary) {\n if (iconLibrary.catalog.library !== manifest.name) {\n problems.push(`provides an icon catalog for '${iconLibrary.catalog.library}' instead of '${manifest.name}'`);\n }\n\n if (iconLibrary.adapter.library !== manifest.name) {\n problems.push(`provides an icon adapter for '${iconLibrary.adapter.library}' instead of '${manifest.name}'`);\n }\n\n if (manifest.iconLibrary && !manifest.iconLibrary.renderers.includes('react')) {\n problems.push(\"provides a React icon adapter but does not list 'react' among its icon renderers\");\n }\n }\n\n return problems;\n}\n\nfunction validateDescriptors(bundle: ScenePackageBundle): string[] {\n const problems: string[] = [];\n const declared = new Set(bundle.manifest.components.map((name) => componentRegistryKey(bundle.manifest.name, name)));\n const described = new Set<string>();\n\n for (const descriptor of bundle.descriptors ?? []) {\n if (!declared.has(descriptor.component)) {\n problems.push(`describes '${descriptor.component}', which the manifest does not declare as a component`);\n }\n\n if (described.has(descriptor.component)) {\n problems.push(`describes '${descriptor.component}' more than once`);\n }\n\n described.add(descriptor.component);\n\n const paths = new Set<string>();\n for (const property of descriptor.properties) {\n if (paths.has(property.path)) {\n problems.push(`'${descriptor.component}' describes the property '${property.path}' more than once`);\n }\n\n paths.add(property.path);\n\n if (property.valueType === PropertyValueType.Collection && property.item === undefined) {\n problems.push(`'${descriptor.component}' describes the collection '${property.path}' without describing its items`);\n }\n\n if (property.valueType === PropertyValueType.Enum && (property.choices ?? []).length === 0) {\n problems.push(`'${descriptor.component}' describes the enum '${property.path}' without choices`);\n }\n }\n }\n\n return problems;\n}\n\n/**\n * Merges the component registries of several bundles into the single registry a renderer consumes.\n *\n * Keys carry their package name, so nothing collides and merge order does not matter — which package wins\n * a *bare* name is decided earlier, by `resolveComponentName` walking the profile's priority order.\n */\nexport function mergePackageRegistries(bundles: ScenePackageBundle[]): ComponentRegistry {\n return Object.assign({}, ...bundles.map((bundle) => bundle.components)) as ComponentRegistry;\n}\n\n/**\n * Collects the icon adapters of several bundles into the registry `SceneIcon` renders through.\n *\n * @throws Error when two bundles provide an adapter for the same library.\n */\nexport function mergeIconAdapters(bundles: ScenePackageBundle[]): IconAdapterRegistry {\n return createIconAdapterRegistry(bundles.flatMap((bundle) => (bundle.iconLibrary ? [bundle.iconLibrary.adapter] : [])));\n}\n"],"names":["componentRegistryKey","packageName","componentName","validatePackageBundle","bundle","problems","manifest","name","components","push","declared","Set","map","key","Object","keys","has","providedLayouts","layouts","layout","providedScreenTemplates","screenTemplates","template","providedDialogTemplates","dialogTemplates","providedThemes","themes","theme","validateIconLibrary","validateDescriptors","iconLibrary","declaresIconLibrary","kind","PackageKind","IconLibrary","undefined","catalog","library","adapter","renderers","includes","described","descriptor","descriptors","component","add","paths","property","properties","path","valueType","PropertyValueType","Collection","item","Enum","choices","length","mergePackageRegistries","bundles","assign","mergeIconAdapters","createIconAdapterRegistry","flatMap"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"CoreNavigationBar.d.ts","sourceRoot":"","sources":["../../../core/CoreNavigationBar.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAC;AAuBvD,wBAAgB,iBAAiB,CAAC,EAAE,OAAO,EAAE,EAAE,wBAAwB,+BA0BtE"}
1
+ {"version":3,"file":"CoreNavigationBar.d.ts","sourceRoot":"","sources":["../../../core/CoreNavigationBar.tsx"],"names":[],"mappings":"AAMA,OAAO,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAC;AAwBvD,wBAAgB,iBAAiB,CAAC,EAAE,OAAO,EAAE,EAAE,wBAAwB,+BA4BtE"}
@@ -1,4 +1,6 @@
1
- import { jsx } from 'react/jsx-runtime';
1
+ import { jsx, jsxs } from 'react/jsx-runtime';
2
+ import { useIconAdapters } from '../icons/IconAdapterContext.js';
3
+ import { SceneIcon } from '../icons/SceneIcon.js';
2
4
 
3
5
  // Copyright (c) Cratis. All rights reserved.
4
6
  // Licensed under the MIT license. See LICENSE file in the project root for full license information.
@@ -13,9 +15,11 @@ function isNavigationBarItem(value) {
13
15
  * It reads `items` from the property bag it is given and nothing else, so it renders the same whether a screen is
14
16
  * being played or edited - configuration is resolved into the bag before it gets here. An item names its destination
15
17
  * as a screen, and activating it emits a host-neutral navigation event, the same as `core:navigate`. An item's icon
16
- * is carried on the node as data attributes for a host to render; icon catalogs are not this component's business.
18
+ * is carried on the node as data attributes and, when an `IconAdapterProvider` is in scope, drawn through the adapter
19
+ * for its library; without one the item shows its label alone. Which icons exist is not this component's business.
17
20
  */ function CoreNavigationBar({ element }) {
18
21
  const items = Array.isArray(element.properties.items) ? element.properties.items.filter(isNavigationBarItem) : [];
22
+ const adapters = useIconAdapters();
19
23
  const title = typeof element.properties.title === 'string' ? element.properties.title : undefined;
20
24
  return /*#__PURE__*/ jsx("nav", {
21
25
  "data-scene-id": element.id,
@@ -29,7 +33,7 @@ function isNavigationBarItem(value) {
29
33
  item
30
34
  }
31
35
  }));
32
- return /*#__PURE__*/ jsx("button", {
36
+ return /*#__PURE__*/ jsxs("button", {
33
37
  type: "button",
34
38
  "data-scene-item": item.id,
35
39
  "data-scene-icon-library": item.icon?.library,
@@ -37,7 +41,13 @@ function isNavigationBarItem(value) {
37
41
  "data-scene-icon-variant": item.icon?.variant,
38
42
  disabled: targetScreen === '',
39
43
  onClick: navigate,
40
- children: item.label
44
+ children: [
45
+ item.icon && adapters ? /*#__PURE__*/ jsx(SceneIcon, {
46
+ reference: item.icon,
47
+ adapters: adapters
48
+ }) : null,
49
+ item.label
50
+ ]
41
51
  }, item.id);
42
52
  })
43
53
  });
@@ -1 +1 @@
1
- {"version":3,"file":"CoreNavigationBar.js","sources":["../../../core/CoreNavigationBar.tsx"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { RegisteredComponentProps } from '../renderer';\n\ninterface NavigationBarItem {\n id: string;\n label: string;\n icon?: { library: string; key: string; variant?: string };\n destination?: { screen: string };\n}\n\nfunction isNavigationBarItem(value: unknown): value is NavigationBarItem {\n const candidate = value as Partial<NavigationBarItem> | null;\n return candidate !== null && typeof candidate === 'object' && typeof candidate.id === 'string' && typeof candidate.label === 'string';\n}\n\n/**\n * The `core:navigationBar` component: a list of navigation items, the first of which a template author normally\n * fixes as Home and the rest of which consumers of the template can add to.\n *\n * It reads `items` from the property bag it is given and nothing else, so it renders the same whether a screen is\n * being played or edited - configuration is resolved into the bag before it gets here. An item names its destination\n * as a screen, and activating it emits a host-neutral navigation event, the same as `core:navigate`. An item's icon\n * is carried on the node as data attributes for a host to render; icon catalogs are not this component's business.\n */\nexport function CoreNavigationBar({ element }: RegisteredComponentProps) {\n const items = Array.isArray(element.properties.items) ? element.properties.items.filter(isNavigationBarItem) : [];\n const title = typeof element.properties.title === 'string' ? element.properties.title : undefined;\n\n return (\n <nav data-scene-id={element.id} aria-label={title}>\n {items.map(item => {\n const targetScreen = item.destination?.screen ?? '';\n const navigate = () => globalThis.dispatchEvent(new CustomEvent('cratis.scene.navigate', { detail: { targetScreen, element, item } }));\n return (\n <button\n key={item.id}\n type='button'\n data-scene-item={item.id}\n data-scene-icon-library={item.icon?.library}\n data-scene-icon-key={item.icon?.key}\n data-scene-icon-variant={item.icon?.variant}\n disabled={targetScreen === ''}\n onClick={navigate}\n >\n {item.label}\n </button>\n );\n })}\n </nav>\n );\n}\n"],"names":["isNavigationBarItem","value","candidate","id","label","CoreNavigationBar","element","items","Array","isArray","properties","filter","title","undefined","_jsx","nav","data-scene-id","aria-label","map","item","targetScreen","destination","screen","navigate","globalThis","dispatchEvent","CustomEvent","detail","button","type","data-scene-item","data-scene-icon-library","icon","library","data-scene-icon-key","key","data-scene-icon-variant","variant","disabled","onClick"],"mappings":";;AAAA;AACA;AAWA,SAASA,oBAAoBC,KAAc,EAAA;AACvC,IAAA,MAAMC,SAAAA,GAAYD,KAAAA;AAClB,IAAA,OAAOC,SAAAA,KAAc,IAAA,IAAQ,OAAOA,SAAAA,KAAc,QAAA,IAAY,OAAOA,SAAAA,CAAUC,EAAE,KAAK,QAAA,IAAY,OAAOD,SAAAA,CAAUE,KAAK,KAAK,QAAA;AACjI;AAEA;;;;;;;;AAQC,IACM,SAASC,iBAAAA,CAAkB,EAAEC,OAAO,EAA4B,EAAA;AACnE,IAAA,MAAMC,QAAQC,KAAAA,CAAMC,OAAO,CAACH,OAAAA,CAAQI,UAAU,CAACH,KAAK,CAAA,GAAID,OAAAA,CAAQI,UAAU,CAACH,KAAK,CAACI,MAAM,CAACX,uBAAuB,EAAE;AACjH,IAAA,MAAMY,KAAAA,GAAQ,OAAON,OAAAA,CAAQI,UAAU,CAACE,KAAK,KAAK,QAAA,GAAWN,OAAAA,CAAQI,UAAU,CAACE,KAAK,GAAGC,SAAAA;AAExF,IAAA,qBACIC,GAAA,CAACC,KAAAA,EAAAA;AAAIC,QAAAA,eAAAA,EAAeV,QAAQH,EAAE;QAAEc,YAAAA,EAAYL,KAAAA;kBACvCL,KAAAA,CAAMW,GAAG,CAACC,CAAAA,IAAAA,GAAAA;AACP,YAAA,MAAMC,YAAAA,GAAeD,IAAAA,CAAKE,WAAW,EAAEC,MAAAA,IAAU,EAAA;AACjD,YAAA,MAAMC,WAAW,IAAMC,UAAAA,CAAWC,aAAa,CAAC,IAAIC,YAAY,uBAAA,EAAyB;oBAAEC,MAAAA,EAAQ;AAAEP,wBAAAA,YAAAA;AAAcd,wBAAAA,OAAAA;AAASa,wBAAAA;AAAK;AAAE,iBAAA,CAAA,CAAA;AACnI,YAAA,qBACIL,GAAA,CAACc,QAAAA,EAAAA;gBAEGC,IAAAA,EAAK,QAAA;AACLC,gBAAAA,iBAAAA,EAAiBX,KAAKhB,EAAE;gBACxB4B,yBAAAA,EAAyBZ,IAAAA,CAAKa,IAAI,EAAEC,OAAAA;gBACpCC,qBAAAA,EAAqBf,IAAAA,CAAKa,IAAI,EAAEG,GAAAA;gBAChCC,yBAAAA,EAAyBjB,IAAAA,CAAKa,IAAI,EAAEK,OAAAA;AACpCC,gBAAAA,QAAAA,EAAUlB,YAAAA,KAAiB,EAAA;gBAC3BmB,OAAAA,EAAShB,QAAAA;AAERJ,gBAAAA,QAAAA,EAAAA,IAAAA,CAAKf;AATDe,aAAAA,EAAAA,IAAAA,CAAKhB,EAAE,CAAA;AAYxB,QAAA,CAAA;;AAGZ;;"}
1
+ {"version":3,"file":"CoreNavigationBar.js","sources":["../../../core/CoreNavigationBar.tsx"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { IconReference } from '@cratis/scene.model';\nimport { useIconAdapters } from '../icons/IconAdapterContext';\nimport { SceneIcon } from '../icons/SceneIcon';\nimport { RegisteredComponentProps } from '../renderer';\n\ninterface NavigationBarItem {\n id: string;\n label: string;\n icon?: IconReference;\n destination?: { screen: string };\n}\n\nfunction isNavigationBarItem(value: unknown): value is NavigationBarItem {\n const candidate = value as Partial<NavigationBarItem> | null;\n return candidate !== null && typeof candidate === 'object' && typeof candidate.id === 'string' && typeof candidate.label === 'string';\n}\n\n/**\n * The `core:navigationBar` component: a list of navigation items, the first of which a template author normally\n * fixes as Home and the rest of which consumers of the template can add to.\n *\n * It reads `items` from the property bag it is given and nothing else, so it renders the same whether a screen is\n * being played or edited - configuration is resolved into the bag before it gets here. An item names its destination\n * as a screen, and activating it emits a host-neutral navigation event, the same as `core:navigate`. An item's icon\n * is carried on the node as data attributes and, when an `IconAdapterProvider` is in scope, drawn through the adapter\n * for its library; without one the item shows its label alone. Which icons exist is not this component's business.\n */\nexport function CoreNavigationBar({ element }: RegisteredComponentProps) {\n const items = Array.isArray(element.properties.items) ? element.properties.items.filter(isNavigationBarItem) : [];\n const adapters = useIconAdapters();\n const title = typeof element.properties.title === 'string' ? element.properties.title : undefined;\n\n return (\n <nav data-scene-id={element.id} aria-label={title}>\n {items.map(item => {\n const targetScreen = item.destination?.screen ?? '';\n const navigate = () => globalThis.dispatchEvent(new CustomEvent('cratis.scene.navigate', { detail: { targetScreen, element, item } }));\n return (\n <button\n key={item.id}\n type='button'\n data-scene-item={item.id}\n data-scene-icon-library={item.icon?.library}\n data-scene-icon-key={item.icon?.key}\n data-scene-icon-variant={item.icon?.variant}\n disabled={targetScreen === ''}\n onClick={navigate}\n >\n {item.icon && adapters ? <SceneIcon reference={item.icon} adapters={adapters} /> : null}\n {item.label}\n </button>\n );\n })}\n </nav>\n );\n}\n"],"names":["isNavigationBarItem","value","candidate","id","label","CoreNavigationBar","element","items","Array","isArray","properties","filter","adapters","useIconAdapters","title","undefined","_jsx","nav","data-scene-id","aria-label","map","item","targetScreen","destination","screen","navigate","globalThis","dispatchEvent","CustomEvent","detail","_jsxs","button","type","data-scene-item","data-scene-icon-library","icon","library","data-scene-icon-key","key","data-scene-icon-variant","variant","disabled","onClick","SceneIcon","reference"],"mappings":";;;;AAAA;AACA;AAcA,SAASA,oBAAoBC,KAAc,EAAA;AACvC,IAAA,MAAMC,SAAAA,GAAYD,KAAAA;AAClB,IAAA,OAAOC,SAAAA,KAAc,IAAA,IAAQ,OAAOA,SAAAA,KAAc,QAAA,IAAY,OAAOA,SAAAA,CAAUC,EAAE,KAAK,QAAA,IAAY,OAAOD,SAAAA,CAAUE,KAAK,KAAK,QAAA;AACjI;AAEA;;;;;;;;;AASC,IACM,SAASC,iBAAAA,CAAkB,EAAEC,OAAO,EAA4B,EAAA;AACnE,IAAA,MAAMC,QAAQC,KAAAA,CAAMC,OAAO,CAACH,OAAAA,CAAQI,UAAU,CAACH,KAAK,CAAA,GAAID,OAAAA,CAAQI,UAAU,CAACH,KAAK,CAACI,MAAM,CAACX,uBAAuB,EAAE;AACjH,IAAA,MAAMY,QAAAA,GAAWC,eAAAA,EAAAA;AACjB,IAAA,MAAMC,KAAAA,GAAQ,OAAOR,OAAAA,CAAQI,UAAU,CAACI,KAAK,KAAK,QAAA,GAAWR,OAAAA,CAAQI,UAAU,CAACI,KAAK,GAAGC,SAAAA;AAExF,IAAA,qBACIC,GAAA,CAACC,KAAAA,EAAAA;AAAIC,QAAAA,eAAAA,EAAeZ,QAAQH,EAAE;QAAEgB,YAAAA,EAAYL,KAAAA;kBACvCP,KAAAA,CAAMa,GAAG,CAACC,CAAAA,IAAAA,GAAAA;AACP,YAAA,MAAMC,YAAAA,GAAeD,IAAAA,CAAKE,WAAW,EAAEC,MAAAA,IAAU,EAAA;AACjD,YAAA,MAAMC,WAAW,IAAMC,UAAAA,CAAWC,aAAa,CAAC,IAAIC,YAAY,uBAAA,EAAyB;oBAAEC,MAAAA,EAAQ;AAAEP,wBAAAA,YAAAA;AAAchB,wBAAAA,OAAAA;AAASe,wBAAAA;AAAK;AAAE,iBAAA,CAAA,CAAA;AACnI,YAAA,qBACIS,IAAA,CAACC,QAAAA,EAAAA;gBAEGC,IAAAA,EAAK,QAAA;AACLC,gBAAAA,iBAAAA,EAAiBZ,KAAKlB,EAAE;gBACxB+B,yBAAAA,EAAyBb,IAAAA,CAAKc,IAAI,EAAEC,OAAAA;gBACpCC,qBAAAA,EAAqBhB,IAAAA,CAAKc,IAAI,EAAEG,GAAAA;gBAChCC,yBAAAA,EAAyBlB,IAAAA,CAAKc,IAAI,EAAEK,OAAAA;AACpCC,gBAAAA,QAAAA,EAAUnB,YAAAA,KAAiB,EAAA;gBAC3BoB,OAAAA,EAASjB,QAAAA;;oBAERJ,IAAAA,CAAKc,IAAI,IAAIvB,QAAAA,iBAAWI,GAAA,CAAC2B,SAAAA,EAAAA;AAAUC,wBAAAA,SAAAA,EAAWvB,KAAKc,IAAI;wBAAEvB,QAAAA,EAAUA;AAAe,qBAAA,CAAA,GAAA,IAAA;AAClFS,oBAAAA,IAAAA,CAAKjB;;AAVDiB,aAAAA,EAAAA,IAAAA,CAAKlB,EAAE,CAAA;AAaxB,QAAA,CAAA;;AAGZ;;"}