@cratis/scene.blueprint.default 4.39.0 → 4.41.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 (281) hide show
  1. package/ComponentName.ts +27 -0
  2. package/defaultBlueprint.ts +1 -0
  3. package/defaultBlueprintComponents.ts +10 -1
  4. package/dist/cjs/ComponentName.js +9 -0
  5. package/dist/cjs/ComponentName.js.map +1 -1
  6. package/dist/cjs/defaultBlueprint.js +18 -1
  7. package/dist/cjs/defaultBlueprint.js.map +1 -1
  8. package/dist/cjs/defaultBlueprintComponentMetadata.js +9 -0
  9. package/dist/cjs/defaultBlueprintComponentMetadata.js.map +1 -1
  10. package/dist/cjs/defaultBlueprintComponents.js +28 -1
  11. package/dist/cjs/defaultBlueprintComponents.js.map +1 -1
  12. package/dist/cjs/foundation/BulkBar.js +62 -0
  13. package/dist/cjs/foundation/BulkBar.js.map +1 -0
  14. package/dist/cjs/foundation/DataList.js +436 -0
  15. package/dist/cjs/foundation/DataList.js.map +1 -0
  16. package/dist/cjs/foundation/FormScreenBody.js +447 -0
  17. package/dist/cjs/foundation/FormScreenBody.js.map +1 -0
  18. package/dist/cjs/foundation/FoundationStates.js +2 -1
  19. package/dist/cjs/foundation/FoundationStates.js.map +1 -1
  20. package/dist/cjs/foundation/GlobalSearch.js +54 -0
  21. package/dist/cjs/foundation/GlobalSearch.js.map +1 -0
  22. package/dist/cjs/foundation/KanbanBoard.js +222 -0
  23. package/dist/cjs/foundation/KanbanBoard.js.map +1 -0
  24. package/dist/cjs/foundation/NotificationsButton.js +45 -0
  25. package/dist/cjs/foundation/NotificationsButton.js.map +1 -0
  26. package/dist/cjs/foundation/SubNavigation.js +72 -0
  27. package/dist/cjs/foundation/SubNavigation.js.map +1 -0
  28. package/dist/cjs/foundation/TabSet.js +101 -0
  29. package/dist/cjs/foundation/TabSet.js.map +1 -0
  30. package/dist/cjs/foundation/WizardProgress.js +185 -0
  31. package/dist/cjs/foundation/WizardProgress.js.map +1 -0
  32. package/dist/cjs/foundation/boardModel.js +67 -0
  33. package/dist/cjs/foundation/boardModel.js.map +1 -0
  34. package/dist/cjs/foundation/formModel.js +158 -0
  35. package/dist/cjs/foundation/formModel.js.map +1 -0
  36. package/dist/cjs/foundation/foundationComponentMetadata.js +54 -0
  37. package/dist/cjs/foundation/foundationComponentMetadata.js.map +1 -1
  38. package/dist/cjs/foundation/foundationDescriptors.js +400 -0
  39. package/dist/cjs/foundation/foundationDescriptors.js.map +1 -1
  40. package/dist/cjs/foundation/foundationSamples.js +303 -0
  41. package/dist/cjs/foundation/foundationSamples.js.map +1 -1
  42. package/dist/cjs/foundation/foundationStrings.js +72 -0
  43. package/dist/cjs/foundation/foundationStrings.js.map +1 -1
  44. package/dist/cjs/foundation/listModel.js +200 -0
  45. package/dist/cjs/foundation/listModel.js.map +1 -0
  46. package/dist/cjs/foundation/tabModel.js +41 -0
  47. package/dist/cjs/foundation/tabModel.js.map +1 -0
  48. package/dist/cjs/foundation/templates/boardScreenTemplate.js +76 -0
  49. package/dist/cjs/foundation/templates/boardScreenTemplate.js.map +1 -0
  50. package/dist/cjs/foundation/templates/dashboardScreenTemplate.js +128 -0
  51. package/dist/cjs/foundation/templates/dashboardScreenTemplate.js.map +1 -0
  52. package/dist/cjs/foundation/templates/formScreenTemplate.js +71 -0
  53. package/dist/cjs/foundation/templates/formScreenTemplate.js.map +1 -0
  54. package/dist/cjs/foundation/templates/index.js +39 -0
  55. package/dist/cjs/foundation/templates/index.js.map +1 -0
  56. package/dist/cjs/foundation/templates/listScreenTemplate.js +124 -0
  57. package/dist/cjs/foundation/templates/listScreenTemplate.js.map +1 -0
  58. package/dist/cjs/foundation/templates/masterDetailScreenTemplate.js +79 -0
  59. package/dist/cjs/foundation/templates/masterDetailScreenTemplate.js.map +1 -0
  60. package/dist/cjs/foundation/templates/recordPageTemplate.js +137 -0
  61. package/dist/cjs/foundation/templates/recordPageTemplate.js.map +1 -0
  62. package/dist/cjs/foundation/templates/templateParts.js +38 -0
  63. package/dist/cjs/foundation/templates/templateParts.js.map +1 -0
  64. package/dist/cjs/foundation/templates/wizardScreenTemplate.js +95 -0
  65. package/dist/cjs/foundation/templates/wizardScreenTemplate.js.map +1 -0
  66. package/dist/cjs/foundation/templates/workspaceScreenTemplate.js +62 -0
  67. package/dist/cjs/foundation/templates/workspaceScreenTemplate.js.map +1 -0
  68. package/dist/cjs/foundation/urlState.js +57 -0
  69. package/dist/cjs/foundation/urlState.js.map +1 -0
  70. package/dist/cjs/foundation/useCompactWidth.js +23 -0
  71. package/dist/cjs/foundation/useCompactWidth.js.map +1 -0
  72. package/dist/cjs/foundation/wizardModel.js +50 -0
  73. package/dist/cjs/foundation/wizardModel.js.map +1 -0
  74. package/dist/cjs/gallery/GalleryScreenPreview.js +76 -4
  75. package/dist/cjs/gallery/GalleryScreenPreview.js.map +1 -1
  76. package/dist/cjs/gallery/applicationChrome.js +18 -1
  77. package/dist/cjs/gallery/applicationChrome.js.map +1 -1
  78. package/dist/cjs/gallery/composeScreen.js +5 -3
  79. package/dist/cjs/gallery/composeScreen.js.map +1 -1
  80. package/dist/cjs/gallery/screens.js +83 -2
  81. package/dist/cjs/gallery/screens.js.map +1 -1
  82. package/dist/cjs/index.js +96 -0
  83. package/dist/cjs/index.js.map +1 -1
  84. package/dist/esm/ComponentName.d.ts +10 -1
  85. package/dist/esm/ComponentName.d.ts.map +1 -1
  86. package/dist/esm/ComponentName.js +9 -0
  87. package/dist/esm/ComponentName.js.map +1 -1
  88. package/dist/esm/defaultBlueprint.d.ts.map +1 -1
  89. package/dist/esm/defaultBlueprint.js +18 -1
  90. package/dist/esm/defaultBlueprint.js.map +1 -1
  91. package/dist/esm/defaultBlueprintComponentMetadata.js +9 -0
  92. package/dist/esm/defaultBlueprintComponentMetadata.js.map +1 -1
  93. package/dist/esm/defaultBlueprintComponents.d.ts.map +1 -1
  94. package/dist/esm/defaultBlueprintComponents.js +28 -1
  95. package/dist/esm/defaultBlueprintComponents.js.map +1 -1
  96. package/dist/esm/foundation/BulkBar.d.ts +4 -0
  97. package/dist/esm/foundation/BulkBar.d.ts.map +1 -0
  98. package/dist/esm/foundation/BulkBar.js +59 -0
  99. package/dist/esm/foundation/BulkBar.js.map +1 -0
  100. package/dist/esm/foundation/DataList.d.ts +3 -0
  101. package/dist/esm/foundation/DataList.d.ts.map +1 -0
  102. package/dist/esm/foundation/DataList.js +434 -0
  103. package/dist/esm/foundation/DataList.js.map +1 -0
  104. package/dist/esm/foundation/FormScreenBody.d.ts +3 -0
  105. package/dist/esm/foundation/FormScreenBody.d.ts.map +1 -0
  106. package/dist/esm/foundation/FormScreenBody.js +445 -0
  107. package/dist/esm/foundation/FormScreenBody.js.map +1 -0
  108. package/dist/esm/foundation/FoundationStates.js +2 -1
  109. package/dist/esm/foundation/FoundationStates.js.map +1 -1
  110. package/dist/esm/foundation/GlobalSearch.d.ts +3 -0
  111. package/dist/esm/foundation/GlobalSearch.d.ts.map +1 -0
  112. package/dist/esm/foundation/GlobalSearch.js +52 -0
  113. package/dist/esm/foundation/GlobalSearch.js.map +1 -0
  114. package/dist/esm/foundation/KanbanBoard.d.ts +3 -0
  115. package/dist/esm/foundation/KanbanBoard.d.ts.map +1 -0
  116. package/dist/esm/foundation/KanbanBoard.js +220 -0
  117. package/dist/esm/foundation/KanbanBoard.js.map +1 -0
  118. package/dist/esm/foundation/NotificationsButton.d.ts +3 -0
  119. package/dist/esm/foundation/NotificationsButton.d.ts.map +1 -0
  120. package/dist/esm/foundation/NotificationsButton.js +43 -0
  121. package/dist/esm/foundation/NotificationsButton.js.map +1 -0
  122. package/dist/esm/foundation/SubNavigation.d.ts +3 -0
  123. package/dist/esm/foundation/SubNavigation.d.ts.map +1 -0
  124. package/dist/esm/foundation/SubNavigation.js +70 -0
  125. package/dist/esm/foundation/SubNavigation.js.map +1 -0
  126. package/dist/esm/foundation/TabSet.d.ts +3 -0
  127. package/dist/esm/foundation/TabSet.d.ts.map +1 -0
  128. package/dist/esm/foundation/TabSet.js +99 -0
  129. package/dist/esm/foundation/TabSet.js.map +1 -0
  130. package/dist/esm/foundation/WizardProgress.d.ts +3 -0
  131. package/dist/esm/foundation/WizardProgress.d.ts.map +1 -0
  132. package/dist/esm/foundation/WizardProgress.js +183 -0
  133. package/dist/esm/foundation/WizardProgress.js.map +1 -0
  134. package/dist/esm/foundation/boardModel.d.ts +22 -0
  135. package/dist/esm/foundation/boardModel.d.ts.map +1 -0
  136. package/dist/esm/foundation/boardModel.js +61 -0
  137. package/dist/esm/foundation/boardModel.js.map +1 -0
  138. package/dist/esm/foundation/formModel.d.ts +48 -0
  139. package/dist/esm/foundation/formModel.d.ts.map +1 -0
  140. package/dist/esm/foundation/formModel.js +147 -0
  141. package/dist/esm/foundation/formModel.js.map +1 -0
  142. package/dist/esm/foundation/foundationComponentMetadata.d.ts.map +1 -1
  143. package/dist/esm/foundation/foundationComponentMetadata.js +54 -0
  144. package/dist/esm/foundation/foundationComponentMetadata.js.map +1 -1
  145. package/dist/esm/foundation/foundationDescriptors.d.ts.map +1 -1
  146. package/dist/esm/foundation/foundationDescriptors.js +400 -0
  147. package/dist/esm/foundation/foundationDescriptors.js.map +1 -1
  148. package/dist/esm/foundation/foundationSamples.d.ts.map +1 -1
  149. package/dist/esm/foundation/foundationSamples.js +303 -0
  150. package/dist/esm/foundation/foundationSamples.js.map +1 -1
  151. package/dist/esm/foundation/foundationStrings.d.ts +72 -0
  152. package/dist/esm/foundation/foundationStrings.d.ts.map +1 -1
  153. package/dist/esm/foundation/foundationStrings.js +72 -0
  154. package/dist/esm/foundation/foundationStrings.js.map +1 -1
  155. package/dist/esm/foundation/index.d.ts +17 -0
  156. package/dist/esm/foundation/index.d.ts.map +1 -1
  157. package/dist/esm/foundation/index.js +17 -0
  158. package/dist/esm/foundation/index.js.map +1 -1
  159. package/dist/esm/foundation/listModel.d.ts +49 -0
  160. package/dist/esm/foundation/listModel.d.ts.map +1 -0
  161. package/dist/esm/foundation/listModel.js +183 -0
  162. package/dist/esm/foundation/listModel.js.map +1 -0
  163. package/dist/esm/foundation/tabModel.d.ts +10 -0
  164. package/dist/esm/foundation/tabModel.d.ts.map +1 -0
  165. package/dist/esm/foundation/tabModel.js +37 -0
  166. package/dist/esm/foundation/tabModel.js.map +1 -0
  167. package/dist/esm/foundation/templates/boardScreenTemplate.d.ts +3 -0
  168. package/dist/esm/foundation/templates/boardScreenTemplate.d.ts.map +1 -0
  169. package/dist/esm/foundation/templates/boardScreenTemplate.js +74 -0
  170. package/dist/esm/foundation/templates/boardScreenTemplate.js.map +1 -0
  171. package/dist/esm/foundation/templates/dashboardScreenTemplate.d.ts +3 -0
  172. package/dist/esm/foundation/templates/dashboardScreenTemplate.d.ts.map +1 -0
  173. package/dist/esm/foundation/templates/dashboardScreenTemplate.js +126 -0
  174. package/dist/esm/foundation/templates/dashboardScreenTemplate.js.map +1 -0
  175. package/dist/esm/foundation/templates/formScreenTemplate.d.ts +3 -0
  176. package/dist/esm/foundation/templates/formScreenTemplate.d.ts.map +1 -0
  177. package/dist/esm/foundation/templates/formScreenTemplate.js +69 -0
  178. package/dist/esm/foundation/templates/formScreenTemplate.js.map +1 -0
  179. package/dist/esm/foundation/templates/index.d.ts +11 -0
  180. package/dist/esm/foundation/templates/index.d.ts.map +1 -0
  181. package/dist/esm/foundation/templates/index.js +25 -0
  182. package/dist/esm/foundation/templates/index.js.map +1 -0
  183. package/dist/esm/foundation/templates/listScreenTemplate.d.ts +3 -0
  184. package/dist/esm/foundation/templates/listScreenTemplate.d.ts.map +1 -0
  185. package/dist/esm/foundation/templates/listScreenTemplate.js +122 -0
  186. package/dist/esm/foundation/templates/listScreenTemplate.js.map +1 -0
  187. package/dist/esm/foundation/templates/masterDetailScreenTemplate.d.ts +3 -0
  188. package/dist/esm/foundation/templates/masterDetailScreenTemplate.d.ts.map +1 -0
  189. package/dist/esm/foundation/templates/masterDetailScreenTemplate.js +77 -0
  190. package/dist/esm/foundation/templates/masterDetailScreenTemplate.js.map +1 -0
  191. package/dist/esm/foundation/templates/recordPageTemplate.d.ts +3 -0
  192. package/dist/esm/foundation/templates/recordPageTemplate.d.ts.map +1 -0
  193. package/dist/esm/foundation/templates/recordPageTemplate.js +135 -0
  194. package/dist/esm/foundation/templates/recordPageTemplate.js.map +1 -0
  195. package/dist/esm/foundation/templates/templateParts.d.ts +6 -0
  196. package/dist/esm/foundation/templates/templateParts.d.ts.map +1 -0
  197. package/dist/esm/foundation/templates/templateParts.js +33 -0
  198. package/dist/esm/foundation/templates/templateParts.js.map +1 -0
  199. package/dist/esm/foundation/templates/wizardScreenTemplate.d.ts +3 -0
  200. package/dist/esm/foundation/templates/wizardScreenTemplate.d.ts.map +1 -0
  201. package/dist/esm/foundation/templates/wizardScreenTemplate.js +93 -0
  202. package/dist/esm/foundation/templates/wizardScreenTemplate.js.map +1 -0
  203. package/dist/esm/foundation/templates/workspaceScreenTemplate.d.ts +3 -0
  204. package/dist/esm/foundation/templates/workspaceScreenTemplate.d.ts.map +1 -0
  205. package/dist/esm/foundation/templates/workspaceScreenTemplate.js +60 -0
  206. package/dist/esm/foundation/templates/workspaceScreenTemplate.js.map +1 -0
  207. package/dist/esm/foundation/urlState.d.ts +4 -0
  208. package/dist/esm/foundation/urlState.d.ts.map +1 -0
  209. package/dist/esm/foundation/urlState.js +53 -0
  210. package/dist/esm/foundation/urlState.js.map +1 -0
  211. package/dist/esm/foundation/useCompactWidth.d.ts +3 -0
  212. package/dist/esm/foundation/useCompactWidth.d.ts.map +1 -0
  213. package/dist/esm/foundation/useCompactWidth.js +20 -0
  214. package/dist/esm/foundation/useCompactWidth.js.map +1 -0
  215. package/dist/esm/foundation/wizardModel.d.ts +16 -0
  216. package/dist/esm/foundation/wizardModel.d.ts.map +1 -0
  217. package/dist/esm/foundation/wizardModel.js +43 -0
  218. package/dist/esm/foundation/wizardModel.js.map +1 -0
  219. package/dist/esm/gallery/GalleryScreenPreview.d.ts +13 -2
  220. package/dist/esm/gallery/GalleryScreenPreview.d.ts.map +1 -1
  221. package/dist/esm/gallery/GalleryScreenPreview.js +75 -5
  222. package/dist/esm/gallery/GalleryScreenPreview.js.map +1 -1
  223. package/dist/esm/gallery/applicationChrome.d.ts.map +1 -1
  224. package/dist/esm/gallery/applicationChrome.js +18 -1
  225. package/dist/esm/gallery/applicationChrome.js.map +1 -1
  226. package/dist/esm/gallery/composeScreen.d.ts.map +1 -1
  227. package/dist/esm/gallery/composeScreen.js +5 -3
  228. package/dist/esm/gallery/composeScreen.js.map +1 -1
  229. package/dist/esm/gallery/screens.d.ts.map +1 -1
  230. package/dist/esm/gallery/screens.js +83 -2
  231. package/dist/esm/gallery/screens.js.map +1 -1
  232. package/dist/esm/index.js +27 -1
  233. package/dist/esm/index.js.map +1 -1
  234. package/dist/esm/tsconfig.tsbuildinfo +1 -1
  235. package/foundation/BulkBar.tsx +38 -0
  236. package/foundation/DataList.tsx +208 -0
  237. package/foundation/FormScreenBody.tsx +196 -0
  238. package/foundation/FoundationStates.tsx +1 -1
  239. package/foundation/GlobalSearch.tsx +33 -0
  240. package/foundation/KanbanBoard.tsx +97 -0
  241. package/foundation/NotificationsButton.tsx +28 -0
  242. package/foundation/SubNavigation.tsx +49 -0
  243. package/foundation/TabSet.tsx +65 -0
  244. package/foundation/WizardProgress.tsx +109 -0
  245. package/foundation/boardModel.ts +64 -0
  246. package/foundation/formModel.ts +146 -0
  247. package/foundation/foundationComponentMetadata.ts +9 -0
  248. package/foundation/foundationDescriptors.ts +195 -0
  249. package/foundation/foundationSamples.ts +56 -0
  250. package/foundation/foundationStrings.ts +72 -0
  251. package/foundation/index.ts +17 -0
  252. package/foundation/listModel.ts +190 -0
  253. package/foundation/tabModel.ts +41 -0
  254. package/foundation/templates/boardScreenTemplate.ts +28 -0
  255. package/foundation/templates/dashboardScreenTemplate.ts +37 -0
  256. package/foundation/templates/formScreenTemplate.ts +28 -0
  257. package/foundation/templates/index.ts +26 -0
  258. package/foundation/templates/listScreenTemplate.ts +37 -0
  259. package/foundation/templates/masterDetailScreenTemplate.ts +28 -0
  260. package/foundation/templates/recordPageTemplate.ts +36 -0
  261. package/foundation/templates/templateParts.ts +30 -0
  262. package/foundation/templates/wizardScreenTemplate.ts +33 -0
  263. package/foundation/templates/workspaceScreenTemplate.ts +27 -0
  264. package/foundation/urlState.ts +52 -0
  265. package/foundation/useCompactWidth.ts +23 -0
  266. package/foundation/wizardModel.ts +54 -0
  267. package/gallery/GalleryScreenPreview.tsx +64 -5
  268. package/gallery/applicationChrome.ts +6 -1
  269. package/gallery/composeScreen.ts +4 -2
  270. package/gallery/screens.ts +16 -1
  271. package/package.json +10 -8
  272. package/sampleData/foundation-en.json +512 -0
  273. package/shell/layout.css +513 -0
  274. package/thumbnails/BoardScreen.svg +15 -0
  275. package/thumbnails/DashboardScreen.svg +18 -0
  276. package/thumbnails/FormScreen.svg +14 -0
  277. package/thumbnails/ListScreen.svg +16 -0
  278. package/thumbnails/MasterDetailScreen.svg +22 -0
  279. package/thumbnails/RecordPage.svg +17 -0
  280. package/thumbnails/WizardScreen.svg +16 -0
  281. package/thumbnails/WorkspaceScreen.svg +12 -0
@@ -0,0 +1,220 @@
1
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
2
+ import { useMemo, useState, useEffect } from 'react';
3
+ import { useValueOutput } from '@cratis/scene.react';
4
+ import { readColumnsOfBoard, readCards, cardsOf, overLimit, moveCard } from './boardModel.js';
5
+ import { readComponentState, ComponentState } from './ComponentState.js';
6
+ import { FoundationIcon } from './FoundationIcon.js';
7
+ import { readFoundationStrings, formatText } from './foundationStrings.js';
8
+ import { readPermissionRule } from './PermissionRule.js';
9
+ import { FoundationFrame } from './StateFrame.js';
10
+
11
+ /**
12
+ * The `kanbanBoard` component: columns mapped to a status or stage, with cards that move between them.
13
+ *
14
+ * `columns` (`id`, `label`, `limit`) and `cards` (`id`, `title`, `column`, `assignee`, up to three `fields`, `badges`) come from a query. A card moves by
15
+ * dragging it to another column **and** by its own "Move to" menu - the keyboard and screen-reader alternative, so nothing depends on a pointer
16
+ * - and every move is announced. Columns show their count and a limit indicator that says "Over the limit" in words, and collapse to a
17
+ * strip. The new arrangement is published as `value` (the cards with their columns) for the screen to save; with `editPermission` not enabled the
18
+ * board is read-only. A card whose column no longer exists is shown in the first column rather than lost.
19
+ */ function KanbanBoard({ element, interactions, bindingOutputs }) {
20
+ const columns = useMemo(()=>readColumnsOfBoard(element.properties.columns), [
21
+ element.properties.columns
22
+ ]);
23
+ const supplied = useMemo(()=>readCards(element.properties.cards), [
24
+ element.properties.cards
25
+ ]);
26
+ const suppliedKey = JSON.stringify(supplied);
27
+ const [cards, setCards] = useState(supplied);
28
+ const [collapsed, setCollapsed] = useState(new Set());
29
+ const [announcement, setAnnouncement] = useState('');
30
+ const [dragging, setDragging] = useState();
31
+ const strings = readFoundationStrings(element);
32
+ const state = readComponentState(element, columns.length > 0);
33
+ const locked = readPermissionRule(element, 'editPermission') !== 'enabled';
34
+ useEffect(()=>setCards(supplied), [
35
+ suppliedKey
36
+ ]);
37
+ useValueOutput(bindingOutputs, cards.map((card)=>({
38
+ id: card.id,
39
+ column: card.column
40
+ })));
41
+ const move = (id, to)=>{
42
+ const card = cards.find((candidate)=>candidate.id === id);
43
+ const target = columns.find((column)=>column.id === to);
44
+ const next = moveCard(columns, cards, id, to);
45
+ if (!card || !target || next === cards) return;
46
+ setCards(next);
47
+ setAnnouncement(formatText(strings.boardMoved, {
48
+ title: card.title,
49
+ column: target.label
50
+ }));
51
+ interactions?.onChange?.();
52
+ };
53
+ const drop = (event, to)=>{
54
+ event.preventDefault();
55
+ if (dragging) move(dragging, to);
56
+ setDragging(undefined);
57
+ };
58
+ const toggle = (id)=>setCollapsed((current)=>{
59
+ const next = new Set(current);
60
+ if (next.has(id)) next.delete(id);
61
+ else next.add(id);
62
+ return next;
63
+ });
64
+ return /*#__PURE__*/ jsx(FoundationFrame, {
65
+ element: element,
66
+ interactions: interactions,
67
+ name: "kanban-board",
68
+ state: state,
69
+ skeleton: [
70
+ 100,
71
+ 100,
72
+ 100
73
+ ],
74
+ children: (state === ComponentState.Ready || state === ComponentState.Partial) && /*#__PURE__*/ jsxs(Fragment, {
75
+ children: [
76
+ /*#__PURE__*/ jsx("div", {
77
+ role: "status",
78
+ "aria-live": "polite",
79
+ className: "foundation-visually-hidden",
80
+ children: announcement
81
+ }),
82
+ /*#__PURE__*/ jsx("div", {
83
+ className: "foundation-board",
84
+ children: columns.map((column)=>{
85
+ const inColumn = cardsOf(columns, cards, column.id);
86
+ const closed = collapsed.has(column.id);
87
+ const over = overLimit(column, inColumn.length);
88
+ return /*#__PURE__*/ jsxs("section", {
89
+ className: "foundation-board-column",
90
+ "data-collapsed": closed,
91
+ "data-over": over,
92
+ "aria-label": formatText(strings.boardColumn, {
93
+ column: column.label,
94
+ count: inColumn.length
95
+ }),
96
+ onDragOver: (event)=>{
97
+ if (!locked) event.preventDefault();
98
+ },
99
+ onDrop: (event)=>{
100
+ if (!locked) drop(event, column.id);
101
+ },
102
+ children: [
103
+ /*#__PURE__*/ jsxs("header", {
104
+ className: "foundation-board-header",
105
+ children: [
106
+ /*#__PURE__*/ jsx("button", {
107
+ type: "button",
108
+ className: "foundation-icon-button",
109
+ "aria-expanded": !closed,
110
+ "aria-label": formatText(closed ? strings.boardExpand : strings.boardCollapse, {
111
+ column: column.label
112
+ }),
113
+ onClick: ()=>toggle(column.id),
114
+ children: /*#__PURE__*/ jsx(FoundationIcon, {
115
+ name: closed ? 'chevron-right' : 'chevron-down'
116
+ })
117
+ }),
118
+ /*#__PURE__*/ jsx("h3", {
119
+ children: column.label
120
+ }),
121
+ /*#__PURE__*/ jsxs("span", {
122
+ className: "foundation-count",
123
+ children: [
124
+ inColumn.length,
125
+ column.limit > 0 ? ` / ${column.limit}` : ''
126
+ ]
127
+ }),
128
+ over && /*#__PURE__*/ jsxs("span", {
129
+ className: "foundation-chip",
130
+ "data-tone": "danger",
131
+ children: [
132
+ /*#__PURE__*/ jsx(FoundationIcon, {
133
+ name: "alert"
134
+ }),
135
+ formatText(strings.boardWipExceeded, {
136
+ limit: column.limit
137
+ })
138
+ ]
139
+ })
140
+ ]
141
+ }),
142
+ !closed && /*#__PURE__*/ jsxs("ul", {
143
+ className: "foundation-board-cards",
144
+ children: [
145
+ inColumn.length === 0 && /*#__PURE__*/ jsx("li", {
146
+ className: "foundation-count",
147
+ children: strings.boardNoCards
148
+ }),
149
+ inColumn.map((card)=>/*#__PURE__*/ jsxs("li", {
150
+ className: "foundation-board-card",
151
+ draggable: !locked,
152
+ onDragStart: ()=>setDragging(card.id),
153
+ onDragEnd: ()=>setDragging(undefined),
154
+ children: [
155
+ /*#__PURE__*/ jsx("strong", {
156
+ children: card.title
157
+ }),
158
+ card.assignee && /*#__PURE__*/ jsxs("span", {
159
+ className: "foundation-count",
160
+ children: [
161
+ /*#__PURE__*/ jsx(FoundationIcon, {
162
+ name: "user"
163
+ }),
164
+ " ",
165
+ card.assignee
166
+ ]
167
+ }),
168
+ card.fields.map((field)=>/*#__PURE__*/ jsxs("span", {
169
+ className: "foundation-board-field",
170
+ children: [
171
+ /*#__PURE__*/ jsx("span", {
172
+ className: "foundation-count",
173
+ children: field.label
174
+ }),
175
+ " ",
176
+ field.value
177
+ ]
178
+ }, field.label)),
179
+ card.badges.length > 0 && /*#__PURE__*/ jsx("span", {
180
+ className: "foundation-board-badges",
181
+ children: card.badges.map((badge)=>/*#__PURE__*/ jsx("span", {
182
+ className: "foundation-chip",
183
+ "data-tone": "neutral",
184
+ children: badge
185
+ }, badge))
186
+ }),
187
+ !locked && /*#__PURE__*/ jsxs("select", {
188
+ className: "foundation-board-move",
189
+ "aria-label": formatText(strings.boardMoveCard, {
190
+ title: card.title
191
+ }),
192
+ value: column.id,
193
+ onChange: (event)=>move(card.id, event.target.value),
194
+ children: [
195
+ /*#__PURE__*/ jsx("option", {
196
+ value: column.id,
197
+ disabled: true,
198
+ children: strings.boardMoveTo
199
+ }),
200
+ columns.filter((other)=>other.id !== column.id).map((other)=>/*#__PURE__*/ jsx("option", {
201
+ value: other.id,
202
+ children: other.label
203
+ }, other.id))
204
+ ]
205
+ })
206
+ ]
207
+ }, card.id))
208
+ ]
209
+ })
210
+ ]
211
+ }, column.id);
212
+ })
213
+ })
214
+ ]
215
+ })
216
+ });
217
+ }
218
+
219
+ export { KanbanBoard };
220
+ //# sourceMappingURL=KanbanBoard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"KanbanBoard.js","sources":["../../../foundation/KanbanBoard.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 { DragEvent, useEffect, useMemo, useState } from 'react';\nimport { RegisteredComponentProps, useValueOutput } from '@cratis/scene.react';\nimport { BoardCard, BoardColumn, cardsOf, moveCard, overLimit, readCards, readColumnsOfBoard } from './boardModel';\nimport { ComponentState, readComponentState } from './ComponentState';\nimport { FoundationIcon } from './FoundationIcon';\nimport { formatText, readFoundationStrings } from './foundationStrings';\nimport { readPermissionRule } from './PermissionRule';\nimport { FoundationFrame } from './StateFrame';\n\n/**\n * The `kanbanBoard` component: columns mapped to a status or stage, with cards that move between them.\n *\n * `columns` (`id`, `label`, `limit`) and `cards` (`id`, `title`, `column`, `assignee`, up to three `fields`, `badges`) come from a query. A card moves by\n * dragging it to another column **and** by its own \"Move to\" menu - the keyboard and screen-reader alternative, so nothing depends on a pointer\n * - and every move is announced. Columns show their count and a limit indicator that says \"Over the limit\" in words, and collapse to a\n * strip. The new arrangement is published as `value` (the cards with their columns) for the screen to save; with `editPermission` not enabled the\n * board is read-only. A card whose column no longer exists is shown in the first column rather than lost.\n */\nexport function KanbanBoard({ element, interactions, bindingOutputs }: RegisteredComponentProps) {\n const columns = useMemo(() => readColumnsOfBoard(element.properties.columns), [element.properties.columns]);\n const supplied = useMemo(() => readCards(element.properties.cards), [element.properties.cards]);\n const suppliedKey = JSON.stringify(supplied);\n const [cards, setCards] = useState<BoardCard[]>(supplied);\n const [collapsed, setCollapsed] = useState<Set<string>>(new Set());\n const [announcement, setAnnouncement] = useState('');\n const [dragging, setDragging] = useState<string | undefined>();\n const strings = readFoundationStrings(element);\n const state = readComponentState(element, columns.length > 0);\n const locked = readPermissionRule(element, 'editPermission') !== 'enabled';\n\n useEffect(() => setCards(supplied), [suppliedKey]);\n useValueOutput(bindingOutputs, cards.map(card => ({ id: card.id, column: card.column })));\n\n const move = (id: string, to: string) => {\n const card = cards.find(candidate => candidate.id === id);\n const target = columns.find(column => column.id === to);\n const next = moveCard(columns, cards, id, to);\n if (!card || !target || next === cards) return;\n setCards(next);\n setAnnouncement(formatText(strings.boardMoved, { title: card.title, column: target.label }));\n interactions?.onChange?.();\n };\n const drop = (event: DragEvent, to: string) => { event.preventDefault(); if (dragging) move(dragging, to); setDragging(undefined); };\n const toggle = (id: string) => setCollapsed(current => { const next = new Set(current); if (next.has(id)) next.delete(id); else next.add(id); return next; });\n\n return (\n <FoundationFrame element={element} interactions={interactions} name='kanban-board' state={state} skeleton={[100, 100, 100]}>\n {(state === ComponentState.Ready || state === ComponentState.Partial) && (\n <>\n <div role='status' aria-live='polite' className='foundation-visually-hidden'>{announcement}</div>\n <div className='foundation-board'>\n {columns.map((column: BoardColumn) => {\n const inColumn = cardsOf(columns, cards, column.id);\n const closed = collapsed.has(column.id);\n const over = overLimit(column, inColumn.length);\n return (\n <section key={column.id} className='foundation-board-column' data-collapsed={closed} data-over={over} aria-label={formatText(strings.boardColumn, { column: column.label, count: inColumn.length })}\n onDragOver={event => { if (!locked) event.preventDefault(); }} onDrop={event => { if (!locked) drop(event, column.id); }}>\n <header className='foundation-board-header'>\n <button type='button' className='foundation-icon-button' aria-expanded={!closed} aria-label={formatText(closed ? strings.boardExpand : strings.boardCollapse, { column: column.label })} onClick={() => toggle(column.id)}>\n <FoundationIcon name={closed ? 'chevron-right' : 'chevron-down'} />\n </button>\n <h3>{column.label}</h3>\n <span className='foundation-count'>{inColumn.length}{column.limit > 0 ? ` / ${column.limit}` : ''}</span>\n {over && <span className='foundation-chip' data-tone='danger'><FoundationIcon name='alert' />{formatText(strings.boardWipExceeded, { limit: column.limit })}</span>}\n </header>\n {!closed && (\n <ul className='foundation-board-cards'>\n {inColumn.length === 0 && <li className='foundation-count'>{strings.boardNoCards}</li>}\n {inColumn.map(card => (\n <li key={card.id} className='foundation-board-card' draggable={!locked} onDragStart={() => setDragging(card.id)} onDragEnd={() => setDragging(undefined)}>\n <strong>{card.title}</strong>\n {card.assignee && <span className='foundation-count'><FoundationIcon name='user' /> {card.assignee}</span>}\n {card.fields.map(field => <span key={field.label} className='foundation-board-field'><span className='foundation-count'>{field.label}</span> {field.value}</span>)}\n {card.badges.length > 0 && <span className='foundation-board-badges'>{card.badges.map(badge => <span key={badge} className='foundation-chip' data-tone='neutral'>{badge}</span>)}</span>}\n {!locked && (\n <select className='foundation-board-move' aria-label={formatText(strings.boardMoveCard, { title: card.title })} value={column.id} onChange={event => move(card.id, event.target.value)}>\n <option value={column.id} disabled>{strings.boardMoveTo}</option>\n {columns.filter(other => other.id !== column.id).map(other => <option key={other.id} value={other.id}>{other.label}</option>)}\n </select>\n )}\n </li>\n ))}\n </ul>\n )}\n </section>\n );\n })}\n </div>\n </>\n )}\n </FoundationFrame>\n );\n}\n"],"names":["KanbanBoard","element","interactions","bindingOutputs","columns","useMemo","readColumnsOfBoard","properties","supplied","readCards","cards","suppliedKey","JSON","stringify","setCards","useState","collapsed","setCollapsed","Set","announcement","setAnnouncement","dragging","setDragging","strings","readFoundationStrings","state","readComponentState","length","locked","readPermissionRule","useEffect","useValueOutput","map","card","id","column","move","to","find","candidate","target","next","moveCard","formatText","boardMoved","title","label","onChange","drop","event","preventDefault","undefined","toggle","current","has","delete","add","_jsx","FoundationFrame","name","skeleton","ComponentState","Ready","Partial","_jsxs","_Fragment","div","role","aria-live","className","inColumn","cardsOf","closed","over","overLimit","section","data-collapsed","data-over","aria-label","boardColumn","count","onDragOver","onDrop","header","button","type","aria-expanded","boardExpand","boardCollapse","onClick","FoundationIcon","h3","span","limit","data-tone","boardWipExceeded","ul","li","boardNoCards","draggable","onDragStart","onDragEnd","strong","assignee","fields","field","value","badges","badge","select","boardMoveCard","option","disabled","boardMoveTo","filter","other"],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { RegisteredComponentProps } from '@cratis/scene.react';
2
+ export declare function NotificationsButton({ element, interactions }: RegisteredComponentProps): import("react").JSX.Element;
3
+ //# sourceMappingURL=NotificationsButton.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NotificationsButton.d.ts","sourceRoot":"","sources":["../../../foundation/NotificationsButton.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAE,wBAAwB,EAAE,MAAM,qBAAqB,CAAC;AAY/D,wBAAgB,mBAAmB,CAAC,EAAE,OAAO,EAAE,YAAY,EAAE,EAAE,wBAAwB,+BAYtF"}
@@ -0,0 +1,43 @@
1
+ import { jsxs, jsx } from 'react/jsx-runtime';
2
+ import { FoundationIcon } from './FoundationIcon.js';
3
+ import { formatNumber, readLocale, NumberFormat } from './formatting.js';
4
+ import { readFoundationStrings, formatText } from './foundationStrings.js';
5
+
6
+ // Copyright (c) Cratis. All rights reserved.
7
+ // Licensed under the MIT license. See LICENSE file in the project root for full license information.
8
+ /**
9
+ * The `notificationsButton` component: the bell of the topbar, with the unread count.
10
+ *
11
+ * `count` is the unread number - bind it to a query - and the button says it in words ("3 unread") as well as in the badge, which is hidden from
12
+ * assistive technology so it is not read twice. Pressing it runs the behaviors attached to the element, which open whatever the application shows its
13
+ * notifications in. Counts above 99 read "99+" in the badge and in full in the words.
14
+ */ function NotificationsButton({ element, interactions }) {
15
+ const strings = readFoundationStrings(element);
16
+ const count = typeof element.properties.count === 'number' && element.properties.count > 0 ? Math.floor(element.properties.count) : 0;
17
+ const spoken = count > 0 ? formatText(strings.notificationsCount, {
18
+ count: formatNumber(count, readLocale(element), NumberFormat.Number, undefined, 0)
19
+ }) : strings.notificationsNone;
20
+ return /*#__PURE__*/ jsxs("button", {
21
+ type: "button",
22
+ className: "foundation foundation-notifications",
23
+ "data-scene-id": element.id,
24
+ onClick: interactions?.onClick,
25
+ children: [
26
+ /*#__PURE__*/ jsx(FoundationIcon, {
27
+ name: "alert"
28
+ }),
29
+ /*#__PURE__*/ jsx("span", {
30
+ className: "foundation-visually-hidden",
31
+ children: `${strings.notificationsLabel}: ${spoken}`
32
+ }),
33
+ count > 0 && /*#__PURE__*/ jsx("span", {
34
+ className: "foundation-notifications-badge",
35
+ "aria-hidden": "true",
36
+ children: count > 99 ? '99+' : count
37
+ })
38
+ ]
39
+ });
40
+ }
41
+
42
+ export { NotificationsButton };
43
+ //# sourceMappingURL=NotificationsButton.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NotificationsButton.js","sources":["../../../foundation/NotificationsButton.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 '@cratis/scene.react';\nimport { FoundationIcon } from './FoundationIcon';\nimport { formatNumber, readLocale, NumberFormat } from './formatting';\nimport { formatText, readFoundationStrings } from './foundationStrings';\n\n/**\n * The `notificationsButton` component: the bell of the topbar, with the unread count.\n *\n * `count` is the unread number - bind it to a query - and the button says it in words (\"3 unread\") as well as in the badge, which is hidden from\n * assistive technology so it is not read twice. Pressing it runs the behaviors attached to the element, which open whatever the application shows its\n * notifications in. Counts above 99 read \"99+\" in the badge and in full in the words.\n */\nexport function NotificationsButton({ element, interactions }: RegisteredComponentProps) {\n const strings = readFoundationStrings(element);\n const count = typeof element.properties.count === 'number' && element.properties.count > 0 ? Math.floor(element.properties.count) : 0;\n const spoken = count > 0 ? formatText(strings.notificationsCount, { count: formatNumber(count, readLocale(element), NumberFormat.Number, undefined, 0) }) : strings.notificationsNone;\n\n return (\n <button type='button' className='foundation foundation-notifications' data-scene-id={element.id} onClick={interactions?.onClick}>\n <FoundationIcon name='alert' />\n <span className='foundation-visually-hidden'>{`${strings.notificationsLabel}: ${spoken}`}</span>\n {count > 0 && <span className='foundation-notifications-badge' aria-hidden='true'>{count > 99 ? '99+' : count}</span>}\n </button>\n );\n}\n"],"names":["NotificationsButton","element","interactions","strings","readFoundationStrings","count","properties","Math","floor","spoken","formatText","notificationsCount","formatNumber","readLocale","NumberFormat","Number","undefined","notificationsNone","_jsxs","button","type","className","data-scene-id","id","onClick","_jsx","FoundationIcon","name","span","notificationsLabel","aria-hidden"],"mappings":";;;;;AAAA;AACA;AAOA;;;;;;AAMC,IACM,SAASA,mBAAAA,CAAoB,EAAEC,OAAO,EAAEC,YAAY,EAA4B,EAAA;AACnF,IAAA,MAAMC,UAAUC,qBAAAA,CAAsBH,OAAAA,CAAAA;IACtC,MAAMI,KAAAA,GAAQ,OAAOJ,OAAAA,CAAQK,UAAU,CAACD,KAAK,KAAK,YAAYJ,OAAAA,CAAQK,UAAU,CAACD,KAAK,GAAG,IAAIE,IAAAA,CAAKC,KAAK,CAACP,OAAAA,CAAQK,UAAU,CAACD,KAAK,CAAA,GAAI,CAAA;AACpI,IAAA,MAAMI,SAASJ,KAAAA,GAAQ,CAAA,GAAIK,UAAAA,CAAWP,OAAAA,CAAQQ,kBAAkB,EAAE;AAAEN,QAAAA,KAAAA,EAAOO,aAAaP,KAAAA,EAAOQ,UAAAA,CAAWZ,UAAUa,YAAAA,CAAaC,MAAM,EAAEC,SAAAA,EAAW,CAAA;AAAG,KAAA,CAAA,GAAKb,QAAQc,iBAAiB;AAErL,IAAA,qBACIC,IAAA,CAACC,QAAAA,EAAAA;QAAOC,IAAAA,EAAK,QAAA;QAASC,SAAAA,EAAU,qCAAA;AAAsCC,QAAAA,eAAAA,EAAerB,QAAQsB,EAAE;AAAEC,QAAAA,OAAAA,EAAStB,YAAAA,EAAcsB,OAAAA;;0BACpHC,GAAA,CAACC,cAAAA,EAAAA;gBAAeC,IAAAA,EAAK;;0BACrBF,GAAA,CAACG,MAAAA,EAAAA;gBAAKP,SAAAA,EAAU,4BAAA;AAA8B,gBAAA,QAAA,EAAA,CAAA,EAAGlB,OAAAA,CAAQ0B,kBAAkB,CAAC,EAAE,EAAEpB,MAAAA,CAAAA;;AAC/EJ,YAAAA,KAAAA,GAAQ,mBAAKoB,GAAA,CAACG,MAAAA,EAAAA;gBAAKP,SAAAA,EAAU,gCAAA;gBAAiCS,aAAAA,EAAY,MAAA;AAAQzB,gBAAAA,QAAAA,EAAAA,KAAAA,GAAQ,KAAK,KAAA,GAAQA;;;;AAGpH;;"}
@@ -0,0 +1,3 @@
1
+ import { RegisteredComponentProps } from '@cratis/scene.react';
2
+ export declare function SubNavigation({ element, interactions, bindingOutputs }: RegisteredComponentProps): import("react").JSX.Element;
3
+ //# sourceMappingURL=SubNavigation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SubNavigation.d.ts","sourceRoot":"","sources":["../../../foundation/SubNavigation.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAE,wBAAwB,EAAkB,MAAM,qBAAqB,CAAC;AAgB/E,wBAAgB,aAAa,CAAC,EAAE,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,EAAE,wBAAwB,+BA4BhG"}
@@ -0,0 +1,70 @@
1
+ import { jsx, jsxs } from 'react/jsx-runtime';
2
+ import { useMemo } from 'react';
3
+ import { useValueOutput } from '@cratis/scene.react';
4
+ import { readOptionalString } from '../shell/elementProperties.js';
5
+ import { readTabs, activeTab } from './tabModel.js';
6
+ import { readComponentState, ComponentState } from './ComponentState.js';
7
+ import { readFoundationStrings } from './foundationStrings.js';
8
+ import { FoundationFrame } from './StateFrame.js';
9
+ import { useUrlState } from './urlState.js';
10
+
11
+ /**
12
+ * The `subNavigation` component: a module's own sections as a tab bar or a left rail.
13
+ *
14
+ * `items` name the sections (id, label, optional count badge), `orientation` is `horizontal` (tabs, default) or `vertical` (a left rail), and
15
+ * `urlKey` keeps the active section in the address so a deep link restores it. It is a navigation landmark, the current section carries
16
+ * `aria-current="page"`, and choosing a section only changes the section: the shell around it keeps its state, which is what makes it a
17
+ * sub-navigation rather than a page change. The id of the active section is the `value` output, which the module's content binds to.
18
+ */ function SubNavigation({ element, interactions, bindingOutputs }) {
19
+ const items = useMemo(()=>readTabs(element.properties.items), [
20
+ element.properties.items
21
+ ]);
22
+ const [requested, setRequested] = useUrlState(readOptionalString(element, 'urlKey'), readOptionalString(element, 'activeItem'));
23
+ const active = activeTab(items, requested);
24
+ const strings = readFoundationStrings(element);
25
+ const state = readComponentState(element, items.length > 0);
26
+ useValueOutput(bindingOutputs, active);
27
+ return /*#__PURE__*/ jsx(FoundationFrame, {
28
+ element: element,
29
+ interactions: interactions,
30
+ name: "sub-navigation",
31
+ state: state,
32
+ skeleton: [
33
+ 50
34
+ ],
35
+ children: state !== ComponentState.Loading && /*#__PURE__*/ jsx("nav", {
36
+ "aria-label": readOptionalString(element, 'label') ?? strings.subNavLabel,
37
+ className: "foundation-subnav",
38
+ "data-orientation": element.properties.orientation === 'vertical' ? 'vertical' : 'horizontal',
39
+ children: /*#__PURE__*/ jsx("ul", {
40
+ children: items.map((item)=>/*#__PURE__*/ jsx("li", {
41
+ children: /*#__PURE__*/ jsxs("a", {
42
+ href: `?${new URLSearchParams({
43
+ [readOptionalString(element, 'urlKey') ?? 'section']: item.id
44
+ }).toString()}`,
45
+ "aria-current": item.id === active ? 'page' : undefined,
46
+ "aria-disabled": item.disabled || undefined,
47
+ className: "foundation-subnav-link",
48
+ onClick: (event)=>{
49
+ event.preventDefault();
50
+ if (!item.disabled) {
51
+ setRequested(item.id);
52
+ interactions?.onSelect?.();
53
+ }
54
+ },
55
+ children: [
56
+ item.label,
57
+ item.badge !== undefined && /*#__PURE__*/ jsx("span", {
58
+ className: "foundation-tab-badge",
59
+ children: item.badge
60
+ })
61
+ ]
62
+ })
63
+ }, item.id))
64
+ })
65
+ })
66
+ });
67
+ }
68
+
69
+ export { SubNavigation };
70
+ //# sourceMappingURL=SubNavigation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SubNavigation.js","sources":["../../../foundation/SubNavigation.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 { useMemo } from 'react';\nimport { RegisteredComponentProps, useValueOutput } from '@cratis/scene.react';\nimport { readOptionalString } from '../shell/elementProperties';\nimport { activeTab, readTabs } from './tabModel';\nimport { ComponentState, readComponentState } from './ComponentState';\nimport { readFoundationStrings } from './foundationStrings';\nimport { FoundationFrame } from './StateFrame';\nimport { useUrlState } from './urlState';\n\n/**\n * The `subNavigation` component: a module's own sections as a tab bar or a left rail.\n *\n * `items` name the sections (id, label, optional count badge), `orientation` is `horizontal` (tabs, default) or `vertical` (a left rail), and\n * `urlKey` keeps the active section in the address so a deep link restores it. It is a navigation landmark, the current section carries\n * `aria-current=\"page\"`, and choosing a section only changes the section: the shell around it keeps its state, which is what makes it a\n * sub-navigation rather than a page change. The id of the active section is the `value` output, which the module's content binds to.\n */\nexport function SubNavigation({ element, interactions, bindingOutputs }: RegisteredComponentProps) {\n const items = useMemo(() => readTabs(element.properties.items), [element.properties.items]);\n const [requested, setRequested] = useUrlState(readOptionalString(element, 'urlKey'), readOptionalString(element, 'activeItem'));\n const active = activeTab(items, requested);\n const strings = readFoundationStrings(element);\n const state = readComponentState(element, items.length > 0);\n\n useValueOutput(bindingOutputs, active);\n\n return (\n <FoundationFrame element={element} interactions={interactions} name='sub-navigation' state={state} skeleton={[50]}>\n {state !== ComponentState.Loading && (\n <nav aria-label={readOptionalString(element, 'label') ?? strings.subNavLabel} className='foundation-subnav' data-orientation={element.properties.orientation === 'vertical' ? 'vertical' : 'horizontal'}>\n <ul>\n {items.map(item => (\n <li key={item.id}>\n <a href={`?${new URLSearchParams({ [readOptionalString(element, 'urlKey') ?? 'section']: item.id }).toString()}`} aria-current={item.id === active ? 'page' : undefined}\n aria-disabled={item.disabled || undefined} className='foundation-subnav-link'\n onClick={event => { event.preventDefault(); if (!item.disabled) { setRequested(item.id); interactions?.onSelect?.(); } }}>\n {item.label}{item.badge !== undefined && <span className='foundation-tab-badge'>{item.badge}</span>}\n </a>\n </li>\n ))}\n </ul>\n </nav>\n )}\n </FoundationFrame>\n );\n}\n"],"names":["SubNavigation","element","interactions","bindingOutputs","items","useMemo","readTabs","properties","requested","setRequested","useUrlState","readOptionalString","active","activeTab","strings","readFoundationStrings","state","readComponentState","length","useValueOutput","_jsx","FoundationFrame","name","skeleton","ComponentState","Loading","nav","aria-label","subNavLabel","className","data-orientation","orientation","ul","map","item","li","_jsxs","a","href","URLSearchParams","id","toString","aria-current","undefined","aria-disabled","disabled","onClick","event","preventDefault","onSelect","label","badge","span"],"mappings":";;;;;;;;;;AAYA;;;;;;;IAQO,SAASA,aAAAA,CAAc,EAAEC,OAAO,EAAEC,YAAY,EAAEC,cAAc,EAA4B,EAAA;IAC7F,MAAMC,KAAAA,GAAQC,QAAQ,IAAMC,QAAAA,CAASL,QAAQM,UAAU,CAACH,KAAK,CAAA,EAAG;QAACH,OAAAA,CAAQM,UAAU,CAACH;AAAM,KAAA,CAAA;IAC1F,MAAM,CAACI,WAAWC,YAAAA,CAAa,GAAGC,YAAYC,kBAAAA,CAAmBV,OAAAA,EAAS,QAAA,CAAA,EAAWU,kBAAAA,CAAmBV,OAAAA,EAAS,YAAA,CAAA,CAAA;IACjH,MAAMW,MAAAA,GAASC,UAAUT,KAAAA,EAAOI,SAAAA,CAAAA;AAChC,IAAA,MAAMM,UAAUC,qBAAAA,CAAsBd,OAAAA,CAAAA;AACtC,IAAA,MAAMe,KAAAA,GAAQC,kBAAAA,CAAmBhB,OAAAA,EAASG,KAAAA,CAAMc,MAAM,GAAG,CAAA,CAAA;AAEzDC,IAAAA,cAAAA,CAAehB,cAAAA,EAAgBS,MAAAA,CAAAA;AAE/B,IAAA,qBACIQ,GAAA,CAACC,eAAAA,EAAAA;QAAgBpB,OAAAA,EAASA,OAAAA;QAASC,YAAAA,EAAcA,YAAAA;QAAcoB,IAAAA,EAAK,gBAAA;QAAiBN,KAAAA,EAAOA,KAAAA;QAAOO,QAAAA,EAAU;AAAC,YAAA;AAAG,SAAA;kBAC5GP,KAAAA,KAAUQ,cAAAA,CAAeC,OAAO,kBAC7BL,GAAA,CAACM,KAAAA,EAAAA;AAAIC,YAAAA,YAAAA,EAAYhB,kBAAAA,CAAmBV,OAAAA,EAAS,OAAA,CAAA,IAAYa,OAAAA,CAAQc,WAAW;YAAEC,SAAAA,EAAU,mBAAA;AAAoBC,YAAAA,kBAAAA,EAAkB7B,QAAQM,UAAU,CAACwB,WAAW,KAAK,aAAa,UAAA,GAAa,YAAA;AACvL,YAAA,QAAA,gBAAAX,GAAA,CAACY,IAAAA,EAAAA;AACI5B,gBAAAA,QAAAA,EAAAA,KAAAA,CAAM6B,GAAG,CAACC,CAAAA,IAAAA,iBACPd,GAAA,CAACe,IAAAA,EAAAA;AACG,wBAAA,QAAA,gBAAAC,IAAA,CAACC,GAAAA,EAAAA;AAAEC,4BAAAA,IAAAA,EAAM,CAAC,CAAC,EAAE,IAAIC,eAAAA,CAAgB;AAAE,gCAAA,CAAC5B,mBAAmBV,OAAAA,EAAS,QAAA,CAAA,IAAa,SAAA,GAAYiC,KAAKM;AAAG,6BAAA,CAAA,CAAGC,QAAQ,EAAA,CAAA,CAAI;AAAEC,4BAAAA,cAAAA,EAAcR,IAAAA,CAAKM,EAAE,KAAK5B,MAAAA,GAAS,MAAA,GAAS+B,SAAAA;4BAC1JC,eAAAA,EAAeV,IAAAA,CAAKW,QAAQ,IAAIF,SAAAA;4BAAWd,SAAAA,EAAU,wBAAA;AACrDiB,4BAAAA,OAAAA,EAASC,CAAAA,KAAAA,GAAAA;AAAWA,gCAAAA,KAAAA,CAAMC,cAAc,EAAA;gCAAI,IAAI,CAACd,IAAAA,CAAKW,QAAQ,EAAE;AAAEpC,oCAAAA,YAAAA,CAAayB,KAAKM,EAAE,CAAA;oCAAGtC,YAAAA,EAAc+C,QAAAA,IAAAA;AAAc,gCAAA;AAAE,4BAAA,CAAA;;AACtHf,gCAAAA,IAAAA,CAAKgB,KAAK;gCAAEhB,IAAAA,CAAKiB,KAAK,KAAKR,SAAAA,kBAAavB,GAAA,CAACgC,MAAAA,EAAAA;oCAAKvB,SAAAA,EAAU,sBAAA;AAAwBK,oCAAAA,QAAAA,EAAAA,IAAAA,CAAKiB;;;;AAJrFjB,qBAAAA,EAAAA,IAAAA,CAAKM,EAAE,CAAA;;;;AAa5C;;"}
@@ -0,0 +1,3 @@
1
+ import { RegisteredComponentProps } from '@cratis/scene.react';
2
+ export declare function TabSet({ element, interactions, slots, bindingOutputs }: RegisteredComponentProps): import("react").JSX.Element;
3
+ //# sourceMappingURL=TabSet.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TabSet.d.ts","sourceRoot":"","sources":["../../../foundation/TabSet.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAE,wBAAwB,EAAkB,MAAM,qBAAqB,CAAC;AAgB/E,wBAAgB,MAAM,CAAC,EAAE,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,cAAc,EAAE,EAAE,wBAAwB,+BA4ChG"}
@@ -0,0 +1,99 @@
1
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
2
+ import { useMemo, useRef } from 'react';
3
+ import { useValueOutput } from '@cratis/scene.react';
4
+ import { readOptionalString } from '../shell/elementProperties.js';
5
+ import { readTabs, activeTab, stepTab } from './tabModel.js';
6
+ import { readComponentState, ComponentState } from './ComponentState.js';
7
+ import { readFoundationStrings } from './foundationStrings.js';
8
+ import { FoundationFrame } from './StateFrame.js';
9
+ import { useUrlState } from './urlState.js';
10
+
11
+ /**
12
+ * The `tabSet` component: a set of tabs, each showing the content filed under its id in the element's slots.
13
+ *
14
+ * `tabs` name the tabs (id, label, optional count badge, disabled); the content of tab `overview` is the slot `overview`. It follows the
15
+ * ARIA tabs pattern - arrows, Home and End move and select, the active tab is the one tab stop, each panel is labelled by its tab - and the
16
+ * active tab is kept in the address under `urlKey` when one is given, so a deep link and a refresh restore it. The id of the active tab is the
17
+ * `value` output. The tabs a record page offers (Overview, Related, Files, History) are configurable by changing this property.
18
+ */ function TabSet({ element, interactions, slots, bindingOutputs }) {
19
+ const tabs = useMemo(()=>readTabs(element.properties.tabs), [
20
+ element.properties.tabs
21
+ ]);
22
+ const [requested, setRequested] = useUrlState(readOptionalString(element, 'urlKey'), readOptionalString(element, 'activeTab'));
23
+ const active = activeTab(tabs, requested);
24
+ const strings = readFoundationStrings(element);
25
+ const state = readComponentState(element, tabs.length > 0);
26
+ const list = useRef(null);
27
+ useValueOutput(bindingOutputs, active);
28
+ const choose = (id, focus = false)=>{
29
+ if (id === undefined) return;
30
+ setRequested(id);
31
+ interactions?.onSelect?.();
32
+ if (focus) requestAnimationFrame(()=>list.current?.querySelector(`[data-tab="${CSS.escape(id)}"]`)?.focus());
33
+ };
34
+ const move = (event)=>{
35
+ const direction = {
36
+ ArrowRight: 'next',
37
+ ArrowDown: 'next',
38
+ ArrowLeft: 'previous',
39
+ ArrowUp: 'previous',
40
+ Home: 'first',
41
+ End: 'last'
42
+ }[event.key];
43
+ if (direction === undefined) return;
44
+ event.preventDefault();
45
+ choose(stepTab(tabs, active, direction), true);
46
+ };
47
+ return /*#__PURE__*/ jsx(FoundationFrame, {
48
+ element: element,
49
+ interactions: interactions,
50
+ name: "tab-set",
51
+ state: state,
52
+ skeleton: [
53
+ 60,
54
+ 100
55
+ ],
56
+ children: state !== ComponentState.Loading && /*#__PURE__*/ jsxs(Fragment, {
57
+ children: [
58
+ /*#__PURE__*/ jsx("div", {
59
+ ref: list,
60
+ role: "tablist",
61
+ "aria-label": readOptionalString(element, 'label') ?? strings.tabsLabel,
62
+ className: "foundation-tabs",
63
+ onKeyDown: move,
64
+ children: tabs.map((tab)=>/*#__PURE__*/ jsxs("button", {
65
+ id: `${element.id}-tab-${tab.id}`,
66
+ "data-tab": tab.id,
67
+ type: "button",
68
+ role: "tab",
69
+ className: "foundation-tab",
70
+ "aria-selected": tab.id === active,
71
+ "aria-controls": `${element.id}-panel-${tab.id}`,
72
+ tabIndex: tab.id === active ? 0 : -1,
73
+ disabled: tab.disabled,
74
+ onClick: ()=>choose(tab.id),
75
+ children: [
76
+ tab.label,
77
+ tab.badge !== undefined && /*#__PURE__*/ jsx("span", {
78
+ className: "foundation-tab-badge",
79
+ children: tab.badge
80
+ })
81
+ ]
82
+ }, tab.id))
83
+ }),
84
+ tabs.map((tab)=>/*#__PURE__*/ jsx("div", {
85
+ id: `${element.id}-panel-${tab.id}`,
86
+ role: "tabpanel",
87
+ "aria-labelledby": `${element.id}-tab-${tab.id}`,
88
+ hidden: tab.id !== active,
89
+ tabIndex: 0,
90
+ className: "foundation-tab-panel",
91
+ children: tab.id === active ? slots?.[tab.id] : undefined
92
+ }, tab.id))
93
+ ]
94
+ })
95
+ });
96
+ }
97
+
98
+ export { TabSet };
99
+ //# sourceMappingURL=TabSet.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TabSet.js","sources":["../../../foundation/TabSet.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 { KeyboardEvent, useMemo, useRef } from 'react';\nimport { RegisteredComponentProps, useValueOutput } from '@cratis/scene.react';\nimport { readOptionalString } from '../shell/elementProperties';\nimport { activeTab, readTabs, stepTab } from './tabModel';\nimport { ComponentState, readComponentState } from './ComponentState';\nimport { readFoundationStrings } from './foundationStrings';\nimport { FoundationFrame } from './StateFrame';\nimport { useUrlState } from './urlState';\n\n/**\n * The `tabSet` component: a set of tabs, each showing the content filed under its id in the element's slots.\n *\n * `tabs` name the tabs (id, label, optional count badge, disabled); the content of tab `overview` is the slot `overview`. It follows the\n * ARIA tabs pattern - arrows, Home and End move and select, the active tab is the one tab stop, each panel is labelled by its tab - and the\n * active tab is kept in the address under `urlKey` when one is given, so a deep link and a refresh restore it. The id of the active tab is the\n * `value` output. The tabs a record page offers (Overview, Related, Files, History) are configurable by changing this property.\n */\nexport function TabSet({ element, interactions, slots, bindingOutputs }: RegisteredComponentProps) {\n const tabs = useMemo(() => readTabs(element.properties.tabs), [element.properties.tabs]);\n const [requested, setRequested] = useUrlState(readOptionalString(element, 'urlKey'), readOptionalString(element, 'activeTab'));\n const active = activeTab(tabs, requested);\n const strings = readFoundationStrings(element);\n const state = readComponentState(element, tabs.length > 0);\n const list = useRef<HTMLDivElement>(null);\n\n useValueOutput(bindingOutputs, active);\n\n const choose = (id: string | undefined, focus = false) => {\n if (id === undefined) return;\n setRequested(id);\n interactions?.onSelect?.();\n if (focus) requestAnimationFrame(() => list.current?.querySelector<HTMLElement>(`[data-tab=\"${CSS.escape(id)}\"]`)?.focus());\n };\n const move = (event: KeyboardEvent) => {\n const direction = { ArrowRight: 'next', ArrowDown: 'next', ArrowLeft: 'previous', ArrowUp: 'previous', Home: 'first', End: 'last' }[event.key] as 'next' | 'previous' | 'first' | 'last' | undefined;\n if (direction === undefined) return;\n event.preventDefault();\n choose(stepTab(tabs, active, direction), true);\n };\n\n return (\n <FoundationFrame element={element} interactions={interactions} name='tab-set' state={state} skeleton={[60, 100]}>\n {state !== ComponentState.Loading && (\n <>\n <div ref={list} role='tablist' aria-label={readOptionalString(element, 'label') ?? strings.tabsLabel} className='foundation-tabs' onKeyDown={move}>\n {tabs.map(tab => (\n <button key={tab.id} id={`${element.id}-tab-${tab.id}`} data-tab={tab.id} type='button' role='tab' className='foundation-tab' aria-selected={tab.id === active}\n aria-controls={`${element.id}-panel-${tab.id}`} tabIndex={tab.id === active ? 0 : -1} disabled={tab.disabled} onClick={() => choose(tab.id)}>\n {tab.label}{tab.badge !== undefined && <span className='foundation-tab-badge'>{tab.badge}</span>}\n </button>\n ))}\n </div>\n {tabs.map(tab => (\n <div key={tab.id} id={`${element.id}-panel-${tab.id}`} role='tabpanel' aria-labelledby={`${element.id}-tab-${tab.id}`} hidden={tab.id !== active} tabIndex={0} className='foundation-tab-panel'>\n {tab.id === active ? slots?.[tab.id] : undefined}\n </div>\n ))}\n </>\n )}\n </FoundationFrame>\n );\n}\n"],"names":["TabSet","element","interactions","slots","bindingOutputs","tabs","useMemo","readTabs","properties","requested","setRequested","useUrlState","readOptionalString","active","activeTab","strings","readFoundationStrings","state","readComponentState","length","list","useRef","useValueOutput","choose","id","focus","undefined","onSelect","requestAnimationFrame","current","querySelector","CSS","escape","move","event","direction","ArrowRight","ArrowDown","ArrowLeft","ArrowUp","Home","End","key","preventDefault","stepTab","_jsx","FoundationFrame","name","skeleton","ComponentState","Loading","_jsxs","_Fragment","div","ref","role","aria-label","tabsLabel","className","onKeyDown","map","tab","button","data-tab","type","aria-selected","aria-controls","tabIndex","disabled","onClick","label","badge","span","aria-labelledby","hidden"],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { RegisteredComponentProps } from '@cratis/scene.react';
2
+ export declare function WizardProgress({ element, interactions, slots, bindingOutputs }: RegisteredComponentProps): import("react").JSX.Element;
3
+ //# sourceMappingURL=WizardProgress.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WizardProgress.d.ts","sourceRoot":"","sources":["../../../foundation/WizardProgress.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAE,wBAAwB,EAAkB,MAAM,qBAAqB,CAAC;AA2C/E,wBAAgB,cAAc,CAAC,EAAE,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,cAAc,EAAE,EAAE,wBAAwB,+BA6DxG"}