@cratis/scene.blueprint.default 4.31.0 → 4.33.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 (226) hide show
  1. package/ComponentName.ts +24 -0
  2. package/defaultBlueprint.ts +2 -1
  3. package/defaultBlueprintComponentMetadata.ts +2 -0
  4. package/defaultBlueprintComponents.ts +9 -0
  5. package/dist/cjs/ComponentName.js +8 -0
  6. package/dist/cjs/ComponentName.js.map +1 -1
  7. package/dist/cjs/defaultBlueprint.js +9 -5
  8. package/dist/cjs/defaultBlueprint.js.map +1 -1
  9. package/dist/cjs/defaultBlueprintComponentMetadata.js +8 -0
  10. package/dist/cjs/defaultBlueprintComponentMetadata.js.map +1 -1
  11. package/dist/cjs/defaultBlueprintComponents.js +21 -1
  12. package/dist/cjs/defaultBlueprintComponents.js.map +1 -1
  13. package/dist/cjs/foundation/ActionButton.js +33 -0
  14. package/dist/cjs/foundation/ActionButton.js.map +1 -0
  15. package/dist/cjs/foundation/ChartWrapper.js +520 -0
  16. package/dist/cjs/foundation/ChartWrapper.js.map +1 -0
  17. package/dist/cjs/foundation/ColumnChooser.js +156 -0
  18. package/dist/cjs/foundation/ColumnChooser.js.map +1 -0
  19. package/dist/cjs/foundation/ComponentState.js +42 -0
  20. package/dist/cjs/foundation/ComponentState.js.map +1 -0
  21. package/dist/cjs/foundation/EmptyState.js +31 -0
  22. package/dist/cjs/foundation/EmptyState.js.map +1 -0
  23. package/dist/cjs/foundation/FilterBuilder.js +307 -0
  24. package/dist/cjs/foundation/FilterBuilder.js.map +1 -0
  25. package/dist/cjs/foundation/FoundationIcon.js +58 -0
  26. package/dist/cjs/foundation/FoundationIcon.js.map +1 -0
  27. package/dist/cjs/foundation/FoundationStates.js +62 -0
  28. package/dist/cjs/foundation/FoundationStates.js.map +1 -0
  29. package/dist/cjs/foundation/PermissionRule.js +22 -0
  30. package/dist/cjs/foundation/PermissionRule.js.map +1 -0
  31. package/dist/cjs/foundation/SavedViewsMenu.js +199 -0
  32. package/dist/cjs/foundation/SavedViewsMenu.js.map +1 -0
  33. package/dist/cjs/foundation/StatCard.js +61 -0
  34. package/dist/cjs/foundation/StatCard.js.map +1 -0
  35. package/dist/cjs/foundation/StateFrame.js +200 -0
  36. package/dist/cjs/foundation/StateFrame.js.map +1 -0
  37. package/dist/cjs/foundation/StatusChip.js +64 -0
  38. package/dist/cjs/foundation/StatusChip.js.map +1 -0
  39. package/dist/cjs/foundation/TrendChip.js +93 -0
  40. package/dist/cjs/foundation/TrendChip.js.map +1 -0
  41. package/dist/cjs/foundation/chartGeometry.js +101 -0
  42. package/dist/cjs/foundation/chartGeometry.js.map +1 -0
  43. package/dist/cjs/foundation/columnModel.js +43 -0
  44. package/dist/cjs/foundation/columnModel.js.map +1 -0
  45. package/dist/cjs/foundation/filterModel.js +123 -0
  46. package/dist/cjs/foundation/filterModel.js.map +1 -0
  47. package/dist/cjs/foundation/formatting.js +85 -0
  48. package/dist/cjs/foundation/formatting.js.map +1 -0
  49. package/dist/cjs/foundation/foundationComponentMetadata.js +69 -0
  50. package/dist/cjs/foundation/foundationComponentMetadata.js.map +1 -0
  51. package/dist/cjs/foundation/foundationDescriptors.js +385 -0
  52. package/dist/cjs/foundation/foundationDescriptors.js.map +1 -0
  53. package/dist/cjs/foundation/foundationSamples.js +201 -0
  54. package/dist/cjs/foundation/foundationSamples.js.map +1 -0
  55. package/dist/cjs/foundation/foundationStrings.js +130 -0
  56. package/dist/cjs/foundation/foundationStrings.js.map +1 -0
  57. package/dist/cjs/foundation/useElementWidth.js +31 -0
  58. package/dist/cjs/foundation/useElementWidth.js.map +1 -0
  59. package/dist/cjs/foundation/viewModel.js +24 -0
  60. package/dist/cjs/foundation/viewModel.js.map +1 -0
  61. package/dist/cjs/index.js +90 -0
  62. package/dist/cjs/index.js.map +1 -1
  63. package/dist/cjs/themes/dark.js +9 -1
  64. package/dist/cjs/themes/dark.js.map +1 -1
  65. package/dist/cjs/themes/light.js +10 -2
  66. package/dist/cjs/themes/light.js.map +1 -1
  67. package/dist/esm/ComponentName.d.ts +9 -1
  68. package/dist/esm/ComponentName.d.ts.map +1 -1
  69. package/dist/esm/ComponentName.js +8 -0
  70. package/dist/esm/ComponentName.js.map +1 -1
  71. package/dist/esm/defaultBlueprint.d.ts.map +1 -1
  72. package/dist/esm/defaultBlueprint.js +9 -5
  73. package/dist/esm/defaultBlueprint.js.map +1 -1
  74. package/dist/esm/defaultBlueprintComponentMetadata.d.ts.map +1 -1
  75. package/dist/esm/defaultBlueprintComponentMetadata.js +8 -0
  76. package/dist/esm/defaultBlueprintComponentMetadata.js.map +1 -1
  77. package/dist/esm/defaultBlueprintComponents.d.ts.map +1 -1
  78. package/dist/esm/defaultBlueprintComponents.js +21 -1
  79. package/dist/esm/defaultBlueprintComponents.js.map +1 -1
  80. package/dist/esm/foundation/ActionButton.d.ts +13 -0
  81. package/dist/esm/foundation/ActionButton.d.ts.map +1 -0
  82. package/dist/esm/foundation/ActionButton.js +31 -0
  83. package/dist/esm/foundation/ActionButton.js.map +1 -0
  84. package/dist/esm/foundation/ChartWrapper.d.ts +5 -0
  85. package/dist/esm/foundation/ChartWrapper.d.ts.map +1 -0
  86. package/dist/esm/foundation/ChartWrapper.js +517 -0
  87. package/dist/esm/foundation/ChartWrapper.js.map +1 -0
  88. package/dist/esm/foundation/ColumnChooser.d.ts +3 -0
  89. package/dist/esm/foundation/ColumnChooser.d.ts.map +1 -0
  90. package/dist/esm/foundation/ColumnChooser.js +154 -0
  91. package/dist/esm/foundation/ColumnChooser.js.map +1 -0
  92. package/dist/esm/foundation/ComponentState.d.ts +12 -0
  93. package/dist/esm/foundation/ComponentState.d.ts.map +1 -0
  94. package/dist/esm/foundation/ComponentState.js +38 -0
  95. package/dist/esm/foundation/ComponentState.js.map +1 -0
  96. package/dist/esm/foundation/EmptyState.d.ts +3 -0
  97. package/dist/esm/foundation/EmptyState.d.ts.map +1 -0
  98. package/dist/esm/foundation/EmptyState.js +29 -0
  99. package/dist/esm/foundation/EmptyState.js.map +1 -0
  100. package/dist/esm/foundation/FilterBuilder.d.ts +3 -0
  101. package/dist/esm/foundation/FilterBuilder.d.ts.map +1 -0
  102. package/dist/esm/foundation/FilterBuilder.js +305 -0
  103. package/dist/esm/foundation/FilterBuilder.js.map +1 -0
  104. package/dist/esm/foundation/Foundation.stories.d.ts +37 -0
  105. package/dist/esm/foundation/Foundation.stories.d.ts.map +1 -0
  106. package/dist/esm/foundation/Foundation.stories.js +34 -0
  107. package/dist/esm/foundation/Foundation.stories.js.map +1 -0
  108. package/dist/esm/foundation/FoundationIcon.d.ts +7 -0
  109. package/dist/esm/foundation/FoundationIcon.d.ts.map +1 -0
  110. package/dist/esm/foundation/FoundationIcon.js +55 -0
  111. package/dist/esm/foundation/FoundationIcon.js.map +1 -0
  112. package/dist/esm/foundation/FoundationStates.d.ts +8 -0
  113. package/dist/esm/foundation/FoundationStates.d.ts.map +1 -0
  114. package/dist/esm/foundation/FoundationStates.js +60 -0
  115. package/dist/esm/foundation/FoundationStates.js.map +1 -0
  116. package/dist/esm/foundation/PermissionRule.d.ts +8 -0
  117. package/dist/esm/foundation/PermissionRule.d.ts.map +1 -0
  118. package/dist/esm/foundation/PermissionRule.js +19 -0
  119. package/dist/esm/foundation/PermissionRule.js.map +1 -0
  120. package/dist/esm/foundation/SavedViewsMenu.d.ts +4 -0
  121. package/dist/esm/foundation/SavedViewsMenu.d.ts.map +1 -0
  122. package/dist/esm/foundation/SavedViewsMenu.js +196 -0
  123. package/dist/esm/foundation/SavedViewsMenu.js.map +1 -0
  124. package/dist/esm/foundation/StatCard.d.ts +3 -0
  125. package/dist/esm/foundation/StatCard.d.ts.map +1 -0
  126. package/dist/esm/foundation/StatCard.js +59 -0
  127. package/dist/esm/foundation/StatCard.js.map +1 -0
  128. package/dist/esm/foundation/StateFrame.d.ts +15 -0
  129. package/dist/esm/foundation/StateFrame.d.ts.map +1 -0
  130. package/dist/esm/foundation/StateFrame.js +197 -0
  131. package/dist/esm/foundation/StateFrame.js.map +1 -0
  132. package/dist/esm/foundation/StatusChip.d.ts +13 -0
  133. package/dist/esm/foundation/StatusChip.d.ts.map +1 -0
  134. package/dist/esm/foundation/StatusChip.js +59 -0
  135. package/dist/esm/foundation/StatusChip.js.map +1 -0
  136. package/dist/esm/foundation/TrendChip.d.ts +18 -0
  137. package/dist/esm/foundation/TrendChip.d.ts.map +1 -0
  138. package/dist/esm/foundation/TrendChip.js +88 -0
  139. package/dist/esm/foundation/TrendChip.js.map +1 -0
  140. package/dist/esm/foundation/chartGeometry.d.ts +34 -0
  141. package/dist/esm/foundation/chartGeometry.d.ts.map +1 -0
  142. package/dist/esm/foundation/chartGeometry.js +93 -0
  143. package/dist/esm/foundation/chartGeometry.js.map +1 -0
  144. package/dist/esm/foundation/columnModel.d.ts +11 -0
  145. package/dist/esm/foundation/columnModel.d.ts.map +1 -0
  146. package/dist/esm/foundation/columnModel.js +38 -0
  147. package/dist/esm/foundation/columnModel.js.map +1 -0
  148. package/dist/esm/foundation/filterModel.d.ts +33 -0
  149. package/dist/esm/foundation/filterModel.d.ts.map +1 -0
  150. package/dist/esm/foundation/filterModel.js +112 -0
  151. package/dist/esm/foundation/filterModel.js.map +1 -0
  152. package/dist/esm/foundation/formatting.d.ts +13 -0
  153. package/dist/esm/foundation/formatting.d.ts.map +1 -0
  154. package/dist/esm/foundation/formatting.js +78 -0
  155. package/dist/esm/foundation/formatting.js.map +1 -0
  156. package/dist/esm/foundation/foundationComponentMetadata.d.ts +3 -0
  157. package/dist/esm/foundation/foundationComponentMetadata.d.ts.map +1 -0
  158. package/dist/esm/foundation/foundationComponentMetadata.js +67 -0
  159. package/dist/esm/foundation/foundationComponentMetadata.js.map +1 -0
  160. package/dist/esm/foundation/foundationDescriptors.d.ts +6 -0
  161. package/dist/esm/foundation/foundationDescriptors.d.ts.map +1 -0
  162. package/dist/esm/foundation/foundationDescriptors.js +380 -0
  163. package/dist/esm/foundation/foundationDescriptors.js.map +1 -0
  164. package/dist/esm/foundation/foundationSamples.d.ts +10 -0
  165. package/dist/esm/foundation/foundationSamples.d.ts.map +1 -0
  166. package/dist/esm/foundation/foundationSamples.js +198 -0
  167. package/dist/esm/foundation/foundationSamples.js.map +1 -0
  168. package/dist/esm/foundation/foundationStrings.d.ts +103 -0
  169. package/dist/esm/foundation/foundationStrings.d.ts.map +1 -0
  170. package/dist/esm/foundation/foundationStrings.js +126 -0
  171. package/dist/esm/foundation/foundationStrings.js.map +1 -0
  172. package/dist/esm/foundation/index.d.ts +25 -0
  173. package/dist/esm/foundation/index.d.ts.map +1 -0
  174. package/dist/esm/foundation/index.js +25 -0
  175. package/dist/esm/foundation/index.js.map +1 -0
  176. package/dist/esm/foundation/useElementWidth.d.ts +3 -0
  177. package/dist/esm/foundation/useElementWidth.d.ts.map +1 -0
  178. package/dist/esm/foundation/useElementWidth.js +29 -0
  179. package/dist/esm/foundation/useElementWidth.js.map +1 -0
  180. package/dist/esm/foundation/viewModel.d.ts +7 -0
  181. package/dist/esm/foundation/viewModel.d.ts.map +1 -0
  182. package/dist/esm/foundation/viewModel.js +22 -0
  183. package/dist/esm/foundation/viewModel.js.map +1 -0
  184. package/dist/esm/gallery/widgets.js +1 -1
  185. package/dist/esm/index.d.ts +1 -0
  186. package/dist/esm/index.d.ts.map +1 -1
  187. package/dist/esm/index.js +24 -0
  188. package/dist/esm/index.js.map +1 -1
  189. package/dist/esm/themes/dark.d.ts.map +1 -1
  190. package/dist/esm/themes/dark.js +9 -1
  191. package/dist/esm/themes/dark.js.map +1 -1
  192. package/dist/esm/themes/light.d.ts.map +1 -1
  193. package/dist/esm/themes/light.js +10 -2
  194. package/dist/esm/themes/light.js.map +1 -1
  195. package/dist/esm/tsconfig.tsbuildinfo +1 -1
  196. package/foundation/ActionButton.tsx +39 -0
  197. package/foundation/ChartWrapper.tsx +252 -0
  198. package/foundation/ColumnChooser.tsx +73 -0
  199. package/foundation/ComponentState.ts +53 -0
  200. package/foundation/EmptyState.tsx +22 -0
  201. package/foundation/FilterBuilder.tsx +144 -0
  202. package/foundation/Foundation.stories.tsx +46 -0
  203. package/foundation/FoundationIcon.tsx +49 -0
  204. package/foundation/FoundationStates.tsx +46 -0
  205. package/foundation/PermissionRule.ts +26 -0
  206. package/foundation/SavedViewsMenu.tsx +94 -0
  207. package/foundation/StatCard.tsx +44 -0
  208. package/foundation/StateFrame.tsx +126 -0
  209. package/foundation/StatusChip.tsx +51 -0
  210. package/foundation/TrendChip.tsx +78 -0
  211. package/foundation/chartGeometry.ts +108 -0
  212. package/foundation/columnModel.ts +39 -0
  213. package/foundation/filterModel.ts +111 -0
  214. package/foundation/formatting.ts +69 -0
  215. package/foundation/foundationComponentMetadata.ts +21 -0
  216. package/foundation/foundationDescriptors.ts +204 -0
  217. package/foundation/foundationSamples.ts +63 -0
  218. package/foundation/foundationStrings.ts +137 -0
  219. package/foundation/index.ts +27 -0
  220. package/foundation/useElementWidth.ts +31 -0
  221. package/foundation/viewModel.ts +21 -0
  222. package/index.ts +1 -0
  223. package/package.json +9 -8
  224. package/shell/layout.css +526 -0
  225. package/themes/dark.ts +8 -0
  226. package/themes/light.ts +9 -1
@@ -0,0 +1,93 @@
1
+ // Copyright (c) Cratis. All rights reserved.
2
+ // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3
+ /** The kinds of chart the wrapper draws (spec Part B 2.3: line, bar, stacked, donut, funnel). */ var ChartKind = /*#__PURE__*/ function(ChartKind) {
4
+ ChartKind["Line"] = "line";
5
+ ChartKind["Bar"] = "bar";
6
+ ChartKind["Stacked"] = "stacked";
7
+ ChartKind["Donut"] = "donut";
8
+ ChartKind["Funnel"] = "funnel";
9
+ return ChartKind;
10
+ }({});
11
+ /** Builds a scale from zero to a rounded-up maximum of the values, in about `target` steps. */ function niceScale(maximum, target = 4) {
12
+ if (!Number.isFinite(maximum) || maximum <= 0) return {
13
+ maximum: 1,
14
+ ticks: [
15
+ 0,
16
+ 1
17
+ ]
18
+ };
19
+ const rough = maximum / target;
20
+ const magnitude = 10 ** Math.floor(Math.log10(rough));
21
+ const residual = rough / magnitude;
22
+ const step = (residual <= 1 ? 1 : residual <= 2 ? 2 : residual <= 5 ? 5 : 10) * magnitude;
23
+ const top = Math.ceil(maximum / step) * step;
24
+ const ticks = [];
25
+ for(let tick = 0; tick <= top + step / 2; tick += step)ticks.push(Number(tick.toFixed(10)));
26
+ return {
27
+ maximum: top,
28
+ ticks
29
+ };
30
+ }
31
+ /** Reads series out of a property value, dropping anything that is not a named list of numbers, so a half-bound chart draws what it has. */ function readSeries(value) {
32
+ if (!Array.isArray(value)) return [];
33
+ return value.flatMap((entry)=>{
34
+ if (typeof entry !== 'object' || entry === null || Array.isArray(entry)) return [];
35
+ const { name, values } = entry;
36
+ if (typeof name !== 'string' || !Array.isArray(values)) return [];
37
+ return [
38
+ {
39
+ name,
40
+ values: values.map((item)=>typeof item === 'number' && Number.isFinite(item) ? item : 0)
41
+ }
42
+ ];
43
+ });
44
+ }
45
+ /** The extent of the values a chart of this kind has to fit: stacked series add up, the others are compared one by one. */ function dataMaximum(kind, series, categoryCount) {
46
+ if (kind === "stacked") {
47
+ return Math.max(0, ...Array.from({
48
+ length: categoryCount
49
+ }, (_, index)=>series.reduce((sum, item)=>sum + Math.max(0, item.values[index] ?? 0), 0)));
50
+ }
51
+ return Math.max(0, ...series.flatMap((item)=>item.values));
52
+ }
53
+ /** Divides the positive values into slices that together make one turn. */ function donutSlices(values) {
54
+ const positive = values.map((value)=>Math.max(0, value));
55
+ const total = positive.reduce((sum, value)=>sum + value, 0);
56
+ if (total === 0) return [];
57
+ let angle = 0;
58
+ return positive.flatMap((value, index)=>{
59
+ if (value === 0) return [];
60
+ const share = value / total;
61
+ const slice = {
62
+ index,
63
+ value,
64
+ share,
65
+ start: angle,
66
+ end: angle + share * Math.PI * 2
67
+ };
68
+ angle = slice.end;
69
+ return [
70
+ slice
71
+ ];
72
+ });
73
+ }
74
+ /** The SVG path of a ring segment between two radii; a full turn is drawn as two halves, because one arc cannot start and end on the same point. */ function ringPath(centerX, centerY, outer, inner, start, end) {
75
+ const point = (radius, angle)=>`${(centerX + radius * Math.sin(angle)).toFixed(2)} ${(centerY - radius * Math.cos(angle)).toFixed(2)}`;
76
+ if (end - start >= Math.PI * 2 - 1e-6) {
77
+ const middle = start + Math.PI;
78
+ return `${ringPath(centerX, centerY, outer, inner, start, middle)} ${ringPath(centerX, centerY, outer, inner, middle, end)}`;
79
+ }
80
+ const large = end - start > Math.PI ? 1 : 0;
81
+ return `M ${point(outer, start)} A ${outer} ${outer} 0 ${large} 1 ${point(outer, end)} L ${point(inner, end)} A ${inner} ${inner} 0 ${large} 0 ${point(inner, start)} Z`;
82
+ }
83
+ /** Sizes the stages of a funnel against the largest value. */ function funnelStages(values) {
84
+ const maximum = Math.max(0, ...values);
85
+ return values.map((value, index)=>({
86
+ index,
87
+ value,
88
+ widthRatio: maximum === 0 ? 0 : Math.max(0, value) / maximum
89
+ }));
90
+ }
91
+
92
+ export { ChartKind, dataMaximum, donutSlices, funnelStages, niceScale, readSeries, ringPath };
93
+ //# sourceMappingURL=chartGeometry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chartGeometry.js","sources":["../../../foundation/chartGeometry.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\n/** The kinds of chart the wrapper draws (spec Part B 2.3: line, bar, stacked, donut, funnel). */\nexport enum ChartKind {\n Line = 'line',\n Bar = 'bar',\n Stacked = 'stacked',\n Donut = 'donut',\n Funnel = 'funnel',\n}\n\n/** One named series of values, one per category. */\nexport interface ChartSeries {\n name: string;\n values: number[];\n}\n\n/** A rounded-up axis maximum and the tick values below it, so an axis reads 0, 25, 50, 75, 100 and not 0, 23.4, 46.8. */\nexport interface ChartScale {\n maximum: number;\n ticks: number[];\n}\n\n/** Builds a scale from zero to a rounded-up maximum of the values, in about `target` steps. */\nexport function niceScale(maximum: number, target = 4): ChartScale {\n if (!Number.isFinite(maximum) || maximum <= 0) return { maximum: 1, ticks: [0, 1] };\n\n const rough = maximum / target;\n const magnitude = 10 ** Math.floor(Math.log10(rough));\n const residual = rough / magnitude;\n const step = (residual <= 1 ? 1 : residual <= 2 ? 2 : residual <= 5 ? 5 : 10) * magnitude;\n const top = Math.ceil(maximum / step) * step;\n const ticks: number[] = [];\n for (let tick = 0; tick <= top + step / 2; tick += step) ticks.push(Number(tick.toFixed(10)));\n return { maximum: top, ticks };\n}\n\n/** Reads series out of a property value, dropping anything that is not a named list of numbers, so a half-bound chart draws what it has. */\nexport function readSeries(value: unknown): ChartSeries[] {\n if (!Array.isArray(value)) return [];\n\n return value.flatMap((entry): ChartSeries[] => {\n if (typeof entry !== 'object' || entry === null || Array.isArray(entry)) return [];\n const { name, values } = entry as Record<string, unknown>;\n if (typeof name !== 'string' || !Array.isArray(values)) return [];\n return [{ name, values: values.map(item => (typeof item === 'number' && Number.isFinite(item) ? item : 0)) }];\n });\n}\n\n/** The extent of the values a chart of this kind has to fit: stacked series add up, the others are compared one by one. */\nexport function dataMaximum(kind: ChartKind, series: ChartSeries[], categoryCount: number): number {\n if (kind === ChartKind.Stacked) {\n return Math.max(0, ...Array.from({ length: categoryCount }, (_, index) => series.reduce((sum, item) => sum + Math.max(0, item.values[index] ?? 0), 0)));\n }\n\n return Math.max(0, ...series.flatMap(item => item.values));\n}\n\n/** A slice of a donut, in radians clockwise from the top. */\nexport interface DonutSlice {\n index: number;\n value: number;\n share: number;\n start: number;\n end: number;\n}\n\n/** Divides the positive values into slices that together make one turn. */\nexport function donutSlices(values: number[]): DonutSlice[] {\n const positive = values.map(value => Math.max(0, value));\n const total = positive.reduce((sum, value) => sum + value, 0);\n if (total === 0) return [];\n\n let angle = 0;\n return positive.flatMap((value, index) => {\n if (value === 0) return [];\n const share = value / total;\n const slice = { index, value, share, start: angle, end: angle + share * Math.PI * 2 };\n angle = slice.end;\n return [slice];\n });\n}\n\n/** The SVG path of a ring segment between two radii; a full turn is drawn as two halves, because one arc cannot start and end on the same point. */\nexport function ringPath(centerX: number, centerY: number, outer: number, inner: number, start: number, end: number): string {\n const point = (radius: number, angle: number) => `${(centerX + radius * Math.sin(angle)).toFixed(2)} ${(centerY - radius * Math.cos(angle)).toFixed(2)}`;\n if (end - start >= Math.PI * 2 - 1e-6) {\n const middle = start + Math.PI;\n return `${ringPath(centerX, centerY, outer, inner, start, middle)} ${ringPath(centerX, centerY, outer, inner, middle, end)}`;\n }\n\n const large = end - start > Math.PI ? 1 : 0;\n return `M ${point(outer, start)} A ${outer} ${outer} 0 ${large} 1 ${point(outer, end)} L ${point(inner, end)} A ${inner} ${inner} 0 ${large} 0 ${point(inner, start)} Z`;\n}\n\n/** One stage of a funnel: a centered bar whose width is its share of the widest stage. */\nexport interface FunnelStage {\n index: number;\n value: number;\n widthRatio: number;\n}\n\n/** Sizes the stages of a funnel against the largest value. */\nexport function funnelStages(values: number[]): FunnelStage[] {\n const maximum = Math.max(0, ...values);\n return values.map((value, index) => ({ index, value, widthRatio: maximum === 0 ? 0 : Math.max(0, value) / maximum }));\n}\n"],"names":["ChartKind","niceScale","maximum","target","Number","isFinite","ticks","rough","magnitude","Math","floor","log10","residual","step","top","ceil","tick","push","toFixed","readSeries","value","Array","isArray","flatMap","entry","name","values","map","item","dataMaximum","kind","series","categoryCount","max","from","length","_","index","reduce","sum","donutSlices","positive","total","angle","share","slice","start","end","PI","ringPath","centerX","centerY","outer","inner","point","radius","sin","cos","middle","large","funnelStages","widthRatio"],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ export interface ChooserColumn {
2
+ id: string;
3
+ label: string;
4
+ visible: boolean;
5
+ locked: boolean;
6
+ }
7
+ export declare function readColumns(value: unknown): ChooserColumn[];
8
+ export declare const visibleColumnIds: (columns: ChooserColumn[]) => string[];
9
+ export declare function moveColumn(columns: ChooserColumn[], index: number, direction: -1 | 1): ChooserColumn[];
10
+ export declare const toggleColumn: (columns: ChooserColumn[], index: number) => ChooserColumn[];
11
+ //# sourceMappingURL=columnModel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"columnModel.d.ts","sourceRoot":"","sources":["../../../foundation/columnModel.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,aAAa;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,OAAO,CAAC;CACnB;AAGD,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,aAAa,EAAE,CAS3D;AAGD,eAAO,MAAM,gBAAgB,YAAa,aAAa,EAAE,KAAG,MAAM,EAAuE,CAAC;AAG1I,wBAAgB,UAAU,CAAC,OAAO,EAAE,aAAa,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,aAAa,EAAE,CAOtG;AAGD,eAAO,MAAM,YAAY,YAAa,aAAa,EAAE,SAAS,MAAM,KAAG,aAAa,EAC4C,CAAC"}
@@ -0,0 +1,38 @@
1
+ // Copyright (c) Cratis. All rights reserved.
2
+ // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3
+ /** One column a table could show. */ /** Reads columns out of a property value; a column is visible unless it says otherwise, and a locked column is always visible. */ function readColumns(value) {
4
+ if (!Array.isArray(value)) return [];
5
+ return value.flatMap((entry)=>{
6
+ if (typeof entry !== 'object' || entry === null || Array.isArray(entry)) return [];
7
+ const { id, label, visible, locked } = entry;
8
+ if (typeof id !== 'string' || id.length === 0) return [];
9
+ return [
10
+ {
11
+ id,
12
+ label: typeof label === 'string' && label.length > 0 ? label : id,
13
+ visible: locked === true || visible !== false,
14
+ locked: locked === true
15
+ }
16
+ ];
17
+ });
18
+ }
19
+ /** The ids of the visible columns, in order: what the chooser publishes and a table binds its columns to. */ const visibleColumnIds = (columns)=>columns.filter((column)=>column.visible).map((column)=>column.id);
20
+ /** Moves a column one place up or down, staying where it is at either end. */ function moveColumn(columns, index, direction) {
21
+ const target = index + direction;
22
+ if (target < 0 || target >= columns.length) return columns;
23
+ const result = [
24
+ ...columns
25
+ ];
26
+ [result[index], result[target]] = [
27
+ result[target],
28
+ result[index]
29
+ ];
30
+ return result;
31
+ }
32
+ /** Shows or hides a column; a locked column cannot be hidden. */ const toggleColumn = (columns, index)=>columns.map((column, position)=>position === index && !column.locked ? {
33
+ ...column,
34
+ visible: !column.visible
35
+ } : column);
36
+
37
+ export { moveColumn, readColumns, toggleColumn, visibleColumnIds };
38
+ //# sourceMappingURL=columnModel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"columnModel.js","sources":["../../../foundation/columnModel.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\n/** One column a table could show. */\nexport interface ChooserColumn {\n id: string;\n label: string;\n visible: boolean;\n locked: boolean;\n}\n\n/** Reads columns out of a property value; a column is visible unless it says otherwise, and a locked column is always visible. */\nexport function readColumns(value: unknown): ChooserColumn[] {\n if (!Array.isArray(value)) return [];\n\n return value.flatMap((entry): ChooserColumn[] => {\n if (typeof entry !== 'object' || entry === null || Array.isArray(entry)) return [];\n const { id, label, visible, locked } = entry as Record<string, unknown>;\n if (typeof id !== 'string' || id.length === 0) return [];\n return [{ id, label: typeof label === 'string' && label.length > 0 ? label : id, visible: locked === true || visible !== false, locked: locked === true }];\n });\n}\n\n/** The ids of the visible columns, in order: what the chooser publishes and a table binds its columns to. */\nexport const visibleColumnIds = (columns: ChooserColumn[]): string[] => columns.filter(column => column.visible).map(column => column.id);\n\n/** Moves a column one place up or down, staying where it is at either end. */\nexport function moveColumn(columns: ChooserColumn[], index: number, direction: -1 | 1): ChooserColumn[] {\n const target = index + direction;\n if (target < 0 || target >= columns.length) return columns;\n\n const result = [...columns];\n [result[index], result[target]] = [result[target], result[index]];\n return result;\n}\n\n/** Shows or hides a column; a locked column cannot be hidden. */\nexport const toggleColumn = (columns: ChooserColumn[], index: number): ChooserColumn[] =>\n columns.map((column, position) => (position === index && !column.locked ? { ...column, visible: !column.visible } : column));\n"],"names":["readColumns","value","Array","isArray","flatMap","entry","id","label","visible","locked","length","visibleColumnIds","columns","filter","column","map","moveColumn","index","direction","target","result","toggleColumn","position"],"mappings":"AAAA;AACA;AAEA,yKASO,SAASA,YAAYC,KAAc,EAAA;AACtC,IAAA,IAAI,CAACC,KAAAA,CAAMC,OAAO,CAACF,KAAAA,CAAAA,EAAQ,OAAO,EAAE;IAEpC,OAAOA,KAAAA,CAAMG,OAAO,CAAC,CAACC,KAAAA,GAAAA;QAClB,IAAI,OAAOA,KAAAA,KAAU,QAAA,IAAYA,KAAAA,KAAU,IAAA,IAAQH,MAAMC,OAAO,CAACE,KAAAA,CAAAA,EAAQ,OAAO,EAAE;QAClF,MAAM,EAAEC,EAAE,EAAEC,KAAK,EAAEC,OAAO,EAAEC,MAAM,EAAE,GAAGJ,KAAAA;QACvC,IAAI,OAAOC,OAAO,QAAA,IAAYA,EAAAA,CAAGI,MAAM,KAAK,CAAA,EAAG,OAAO,EAAE;QACxD,OAAO;AAAC,YAAA;AAAEJ,gBAAAA,EAAAA;AAAIC,gBAAAA,KAAAA,EAAO,OAAOA,KAAAA,KAAU,QAAA,IAAYA,MAAMG,MAAM,GAAG,IAAIH,KAAAA,GAAQD,EAAAA;gBAAIE,OAAAA,EAASC,MAAAA,KAAW,QAAQD,OAAAA,KAAY,KAAA;AAAOC,gBAAAA,MAAAA,EAAQA,MAAAA,KAAW;AAAK;AAAE,SAAA;AAC9J,IAAA,CAAA,CAAA;AACJ;AAEA,8GACO,MAAME,gBAAAA,GAAmB,CAACC,OAAAA,GAAuCA,OAAAA,CAAQC,MAAM,CAACC,CAAAA,SAAUA,MAAAA,CAAON,OAAO,EAAEO,GAAG,CAACD,CAAAA,MAAAA,GAAUA,MAAAA,CAAOR,EAAE;AAExI,+EACO,SAASU,UAAAA,CAAWJ,OAAwB,EAAEK,KAAa,EAAEC,SAAiB,EAAA;AACjF,IAAA,MAAMC,SAASF,KAAAA,GAAQC,SAAAA;AACvB,IAAA,IAAIC,SAAS,CAAA,IAAKA,MAAAA,IAAUP,OAAAA,CAAQF,MAAM,EAAE,OAAOE,OAAAA;AAEnD,IAAA,MAAMQ,MAAAA,GAAS;AAAIR,QAAAA,GAAAA;AAAQ,KAAA;IAC3B,CAACQ,MAAM,CAACH,KAAAA,CAAM,EAAEG,MAAM,CAACD,MAAAA,CAAO,CAAC,GAAG;AAACC,QAAAA,MAAM,CAACD,MAAAA,CAAO;AAAEC,QAAAA,MAAM,CAACH,KAAAA;AAAO,KAAA;IACjE,OAAOG,MAAAA;AACX;AAEA,kEACO,MAAMC,eAAe,CAACT,OAAAA,EAA0BK,QACnDL,OAAAA,CAAQG,GAAG,CAAC,CAACD,QAAQQ,QAAAA,GAAcA,QAAAA,KAAaL,SAAS,CAACH,MAAAA,CAAOL,MAAM,GAAG;AAAE,YAAA,GAAGK,MAAM;YAAEN,OAAAA,EAAS,CAACM,OAAON;AAAQ,SAAA,GAAIM,MAAAA;;"}
@@ -0,0 +1,33 @@
1
+ export declare enum FilterFieldType {
2
+ Text = "text",
3
+ Number = "number",
4
+ Date = "date",
5
+ Select = "select",
6
+ Boolean = "boolean"
7
+ }
8
+ export interface FilterField {
9
+ name: string;
10
+ label: string;
11
+ type: FilterFieldType;
12
+ options: string[];
13
+ }
14
+ export interface FilterCondition {
15
+ field: string;
16
+ operator: string;
17
+ value: string;
18
+ }
19
+ export interface FilterGroup {
20
+ operator: 'and' | 'or';
21
+ conditions: FilterCondition[];
22
+ groups: FilterGroup[];
23
+ }
24
+ export declare const maximumFilterDepth = 3;
25
+ export declare const emptyFilter: () => FilterGroup;
26
+ export declare const filterOperators: Record<FilterFieldType, string[]>;
27
+ export declare const valuelessOperators: string[];
28
+ export declare function readFilterFields(value: unknown): FilterField[];
29
+ export declare function normalizeFilter(value: unknown, fields: FilterField[], depth?: number): FilterGroup;
30
+ export declare function countActiveConditions(group: FilterGroup): number;
31
+ export declare function updateGroupAt(root: FilterGroup, path: number[], change: (group: FilterGroup) => FilterGroup): FilterGroup;
32
+ export declare function newCondition(fields: FilterField[]): FilterCondition;
33
+ //# sourceMappingURL=filterModel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filterModel.d.ts","sourceRoot":"","sources":["../../../foundation/filterModel.ts"],"names":[],"mappings":"AAIA,oBAAY,eAAe;IACvB,IAAI,SAAS;IACb,MAAM,WAAW;IACjB,IAAI,SAAS;IACb,MAAM,WAAW;IACjB,OAAO,YAAY;CACtB;AAGD,MAAM,WAAW,WAAW;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,eAAe,CAAC;IACtB,OAAO,EAAE,MAAM,EAAE,CAAC;CACrB;AAGD,MAAM,WAAW,eAAe;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;CACjB;AAGD,MAAM,WAAW,WAAW;IACxB,QAAQ,EAAE,KAAK,GAAG,IAAI,CAAC;IACvB,UAAU,EAAE,eAAe,EAAE,CAAC;IAC9B,MAAM,EAAE,WAAW,EAAE,CAAC;CACzB;AAGD,eAAO,MAAM,kBAAkB,IAAI,CAAC;AAGpC,eAAO,MAAM,WAAW,QAAO,WAAgE,CAAC;AAGhG,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,eAAe,EAAE,MAAM,EAAE,CAM7D,CAAC;AAGF,eAAO,MAAM,kBAAkB,UAA+B,CAAC;AAG/D,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,WAAW,EAAE,CAc9D;AAGD,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,EAAE,KAAK,SAAI,GAAG,WAAW,CAoB7F;AAGD,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,CAGhE;AAGD,wBAAgB,aAAa,CAAC,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,WAAW,GAAG,WAAW,CAKzH;AAGD,wBAAgB,YAAY,CAAC,MAAM,EAAE,WAAW,EAAE,GAAG,eAAe,CAGnE"}
@@ -0,0 +1,112 @@
1
+ // Copyright (c) Cratis. All rights reserved.
2
+ // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3
+ /** What a filterable field holds, which decides the operators offered for it. */ var FilterFieldType = /*#__PURE__*/ function(FilterFieldType) {
4
+ FilterFieldType["Text"] = "text";
5
+ FilterFieldType["Number"] = "number";
6
+ FilterFieldType["Date"] = "date";
7
+ FilterFieldType["Select"] = "select";
8
+ FilterFieldType["Boolean"] = "boolean";
9
+ return FilterFieldType;
10
+ }({});
11
+ /** The deepest a group may nest; deeper filters are unreadable, and a runaway value is cut rather than rendered forever. */ const maximumFilterDepth = 3;
12
+ /** An empty group. */ const emptyFilter = ()=>({
13
+ operator: 'and',
14
+ conditions: [],
15
+ groups: []
16
+ });
17
+ /** The operators of each field type, in the order they are offered; the first is the default. */ const filterOperators = {
18
+ ["text"]: [
19
+ 'contains',
20
+ 'equals',
21
+ 'notEquals',
22
+ 'startsWith',
23
+ 'isEmpty'
24
+ ],
25
+ ["number"]: [
26
+ 'equals',
27
+ 'notEquals',
28
+ 'greater',
29
+ 'greaterOrEqual',
30
+ 'less',
31
+ 'lessOrEqual'
32
+ ],
33
+ ["date"]: [
34
+ 'on',
35
+ 'before',
36
+ 'after'
37
+ ],
38
+ ["select"]: [
39
+ 'is',
40
+ 'isNot'
41
+ ],
42
+ ["boolean"]: [
43
+ 'true',
44
+ 'false'
45
+ ]
46
+ };
47
+ /** The operators that need no value to compare with. */ const valuelessOperators = [
48
+ 'isEmpty',
49
+ 'true',
50
+ 'false'
51
+ ];
52
+ /** Reads fields out of a property value, dropping entries without a name, and defaulting what is unknown to text. */ function readFilterFields(value) {
53
+ if (!Array.isArray(value)) return [];
54
+ return value.flatMap((entry)=>{
55
+ if (typeof entry !== 'object' || entry === null || Array.isArray(entry)) return [];
56
+ const { name, label, type, options } = entry;
57
+ if (typeof name !== 'string' || name.length === 0) return [];
58
+ return [
59
+ {
60
+ name,
61
+ label: typeof label === 'string' && label.length > 0 ? label : name,
62
+ type: Object.values(FilterFieldType).includes(type) ? type : "text",
63
+ options: Array.isArray(options) ? options.filter((option)=>typeof option === 'string') : []
64
+ }
65
+ ];
66
+ });
67
+ }
68
+ /** Reads a filter out of a property value, keeping the conditions on known fields with operators their type offers. */ function normalizeFilter(value, fields, depth = 1) {
69
+ if (typeof value !== 'object' || value === null || Array.isArray(value)) return emptyFilter();
70
+ const { operator, conditions, groups } = value;
71
+ return {
72
+ operator: operator === 'or' ? 'or' : 'and',
73
+ conditions: Array.isArray(conditions) ? conditions.flatMap((entry)=>{
74
+ if (typeof entry !== 'object' || entry === null) return [];
75
+ const condition = entry;
76
+ const field = fields.find((candidate)=>candidate.name === condition.field);
77
+ if (!field) return [];
78
+ const operators = filterOperators[field.type];
79
+ return [
80
+ {
81
+ field: field.name,
82
+ operator: typeof condition.operator === 'string' && operators.includes(condition.operator) ? condition.operator : operators[0],
83
+ value: typeof condition.value === 'string' ? condition.value : typeof condition.value === 'number' ? String(condition.value) : ''
84
+ }
85
+ ];
86
+ }) : [],
87
+ groups: depth < maximumFilterDepth && Array.isArray(groups) ? groups.map((group)=>normalizeFilter(group, fields, depth + 1)) : []
88
+ };
89
+ }
90
+ /** How many conditions are in force: a condition that needs a value and has none is not filtering anything. */ function countActiveConditions(group) {
91
+ const own = group.conditions.filter((condition)=>valuelessOperators.includes(condition.operator) || condition.value.trim().length > 0).length;
92
+ return own + group.groups.reduce((sum, nested)=>sum + countActiveConditions(nested), 0);
93
+ }
94
+ /** Applies a change to the group at a path of nested group indexes, leaving the rest as it was. */ function updateGroupAt(root, path, change) {
95
+ if (path.length === 0) return change(root);
96
+ const [index, ...rest] = path;
97
+ return {
98
+ ...root,
99
+ groups: root.groups.map((group, position)=>position === index ? updateGroupAt(group, rest, change) : group)
100
+ };
101
+ }
102
+ /** A new condition on the first field, with that field's default operator. */ function newCondition(fields) {
103
+ const field = fields[0];
104
+ return {
105
+ field: field?.name ?? '',
106
+ operator: field ? filterOperators[field.type][0] : 'contains',
107
+ value: ''
108
+ };
109
+ }
110
+
111
+ export { FilterFieldType, countActiveConditions, emptyFilter, filterOperators, maximumFilterDepth, newCondition, normalizeFilter, readFilterFields, updateGroupAt, valuelessOperators };
112
+ //# sourceMappingURL=filterModel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filterModel.js","sources":["../../../foundation/filterModel.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\n/** What a filterable field holds, which decides the operators offered for it. */\nexport enum FilterFieldType {\n Text = 'text',\n Number = 'number',\n Date = 'date',\n Select = 'select',\n Boolean = 'boolean',\n}\n\n/** A field a filter can be built on. */\nexport interface FilterField {\n name: string;\n label: string;\n type: FilterFieldType;\n options: string[];\n}\n\n/** One test of a field. */\nexport interface FilterCondition {\n field: string;\n operator: string;\n value: string;\n}\n\n/** Conditions and nested groups joined by AND or OR. */\nexport interface FilterGroup {\n operator: 'and' | 'or';\n conditions: FilterCondition[];\n groups: FilterGroup[];\n}\n\n/** The deepest a group may nest; deeper filters are unreadable, and a runaway value is cut rather than rendered forever. */\nexport const maximumFilterDepth = 3;\n\n/** An empty group. */\nexport const emptyFilter = (): FilterGroup => ({ operator: 'and', conditions: [], groups: [] });\n\n/** The operators of each field type, in the order they are offered; the first is the default. */\nexport const filterOperators: Record<FilterFieldType, string[]> = {\n [FilterFieldType.Text]: ['contains', 'equals', 'notEquals', 'startsWith', 'isEmpty'],\n [FilterFieldType.Number]: ['equals', 'notEquals', 'greater', 'greaterOrEqual', 'less', 'lessOrEqual'],\n [FilterFieldType.Date]: ['on', 'before', 'after'],\n [FilterFieldType.Select]: ['is', 'isNot'],\n [FilterFieldType.Boolean]: ['true', 'false'],\n};\n\n/** The operators that need no value to compare with. */\nexport const valuelessOperators = ['isEmpty', 'true', 'false'];\n\n/** Reads fields out of a property value, dropping entries without a name, and defaulting what is unknown to text. */\nexport function readFilterFields(value: unknown): FilterField[] {\n if (!Array.isArray(value)) return [];\n\n return value.flatMap((entry): FilterField[] => {\n if (typeof entry !== 'object' || entry === null || Array.isArray(entry)) return [];\n const { name, label, type, options } = entry as Record<string, unknown>;\n if (typeof name !== 'string' || name.length === 0) return [];\n return [{\n name,\n label: typeof label === 'string' && label.length > 0 ? label : name,\n type: (Object.values(FilterFieldType) as string[]).includes(type as string) ? (type as FilterFieldType) : FilterFieldType.Text,\n options: Array.isArray(options) ? options.filter((option): option is string => typeof option === 'string') : [],\n }];\n });\n}\n\n/** Reads a filter out of a property value, keeping the conditions on known fields with operators their type offers. */\nexport function normalizeFilter(value: unknown, fields: FilterField[], depth = 1): FilterGroup {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) return emptyFilter();\n\n const { operator, conditions, groups } = value as Record<string, unknown>;\n return {\n operator: operator === 'or' ? 'or' : 'and',\n conditions: Array.isArray(conditions) ? conditions.flatMap((entry): FilterCondition[] => {\n if (typeof entry !== 'object' || entry === null) return [];\n const condition = entry as Record<string, unknown>;\n const field = fields.find(candidate => candidate.name === condition.field);\n if (!field) return [];\n const operators = filterOperators[field.type];\n return [{\n field: field.name,\n operator: typeof condition.operator === 'string' && operators.includes(condition.operator) ? condition.operator : operators[0],\n value: typeof condition.value === 'string' ? condition.value : typeof condition.value === 'number' ? String(condition.value) : '',\n }];\n }) : [],\n groups: depth < maximumFilterDepth && Array.isArray(groups) ? groups.map(group => normalizeFilter(group, fields, depth + 1)) : [],\n };\n}\n\n/** How many conditions are in force: a condition that needs a value and has none is not filtering anything. */\nexport function countActiveConditions(group: FilterGroup): number {\n const own = group.conditions.filter(condition => valuelessOperators.includes(condition.operator) || condition.value.trim().length > 0).length;\n return own + group.groups.reduce((sum, nested) => sum + countActiveConditions(nested), 0);\n}\n\n/** Applies a change to the group at a path of nested group indexes, leaving the rest as it was. */\nexport function updateGroupAt(root: FilterGroup, path: number[], change: (group: FilterGroup) => FilterGroup): FilterGroup {\n if (path.length === 0) return change(root);\n\n const [index, ...rest] = path;\n return { ...root, groups: root.groups.map((group, position) => (position === index ? updateGroupAt(group, rest, change) : group)) };\n}\n\n/** A new condition on the first field, with that field's default operator. */\nexport function newCondition(fields: FilterField[]): FilterCondition {\n const field = fields[0];\n return { field: field?.name ?? '', operator: field ? filterOperators[field.type][0] : 'contains', value: '' };\n}\n"],"names":["FilterFieldType","maximumFilterDepth","emptyFilter","operator","conditions","groups","filterOperators","valuelessOperators","readFilterFields","value","Array","isArray","flatMap","entry","name","label","type","options","length","Object","values","includes","filter","option","normalizeFilter","fields","depth","condition","field","find","candidate","operators","String","map","group","countActiveConditions","own","trim","reduce","sum","nested","updateGroupAt","root","path","change","index","rest","position","newCondition"],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import { ExternalComponent } from '@cratis/scene.model';
2
+ export declare enum NumberFormat {
3
+ Number = "number",
4
+ Currency = "currency",
5
+ Percent = "percent",
6
+ Compact = "compact"
7
+ }
8
+ export declare function readLocale(element: ExternalComponent): string;
9
+ export declare function isRightToLeft(locale: string): boolean;
10
+ export declare function formatNumber(value: number, locale: string, format?: NumberFormat, currency?: string, maximumFractionDigits?: number): string;
11
+ export declare function readNumberFormat(element: ExternalComponent, property?: string): NumberFormat;
12
+ export declare function formatDate(value: unknown, locale: string, withTime?: boolean): string;
13
+ //# sourceMappingURL=formatting.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"formatting.d.ts","sourceRoot":"","sources":["../../../foundation/formatting.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAGxD,oBAAY,YAAY;IACpB,MAAM,WAAW;IACjB,QAAQ,aAAa;IACrB,OAAO,YAAY;IACnB,OAAO,YAAY;CACtB;AAMD,wBAAgB,UAAU,CAAC,OAAO,EAAE,iBAAiB,GAAG,MAAM,CAK7D;AAGD,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAQrD;AAGD,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAE,YAAkC,EAAE,QAAQ,SAAQ,EAAE,qBAAqB,CAAC,EAAE,MAAM,GAAG,MAAM,CAehK;AAGD,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,iBAAiB,EAAE,QAAQ,SAAW,GAAG,YAAY,CAG9F;AAGD,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,UAAQ,GAAG,MAAM,CAQnF"}
@@ -0,0 +1,78 @@
1
+ // Copyright (c) Cratis. All rights reserved.
2
+ // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3
+ /** How a number is presented. */ var NumberFormat = /*#__PURE__*/ function(NumberFormat) {
4
+ NumberFormat["Number"] = "number";
5
+ NumberFormat["Currency"] = "currency";
6
+ NumberFormat["Percent"] = "percent";
7
+ NumberFormat["Compact"] = "compact";
8
+ return NumberFormat;
9
+ }({});
10
+ /**
11
+ * The locale a component formats dates, numbers and currency in: the element's `locale`, else the document language, else the
12
+ * runtime's. Formatting never goes through a fixed locale, so the same screen reads correctly in every one.
13
+ */ function readLocale(element) {
14
+ const supplied = element.properties.locale;
15
+ if (typeof supplied === 'string' && supplied.length > 0) return supplied;
16
+ if (typeof document !== 'undefined' && document.documentElement.lang) return document.documentElement.lang;
17
+ return typeof navigator !== 'undefined' && navigator.language ? navigator.language : 'en';
18
+ }
19
+ /** Whether the locale reads right to left, so a component can mirror what direction-sensitive CSS cannot. */ function isRightToLeft(locale) {
20
+ try {
21
+ const info = new Intl.Locale(locale);
22
+ const direction = info.getTextInfo?.().direction ?? info.textInfo?.direction;
23
+ return direction === 'rtl';
24
+ } catch {
25
+ return false;
26
+ }
27
+ }
28
+ /** Formats a number for a locale, as a plain number, currency, percent (the value is the percentage, 12.5 is 12.5%) or compact. */ function formatNumber(value, locale, format = "number", currency = 'USD', maximumFractionDigits) {
29
+ try {
30
+ switch(format){
31
+ case "currency":
32
+ return new Intl.NumberFormat(locale, {
33
+ style: 'currency',
34
+ currency,
35
+ ...maximumFractionDigits === undefined ? {} : {
36
+ maximumFractionDigits
37
+ }
38
+ }).format(value);
39
+ case "percent":
40
+ return new Intl.NumberFormat(locale, {
41
+ style: 'percent',
42
+ maximumFractionDigits: maximumFractionDigits ?? 1
43
+ }).format(value / 100);
44
+ case "compact":
45
+ return new Intl.NumberFormat(locale, {
46
+ notation: 'compact',
47
+ maximumFractionDigits: maximumFractionDigits ?? 1
48
+ }).format(value);
49
+ default:
50
+ return new Intl.NumberFormat(locale, {
51
+ maximumFractionDigits: maximumFractionDigits ?? 2
52
+ }).format(value);
53
+ }
54
+ } catch {
55
+ return String(value);
56
+ }
57
+ }
58
+ /** Reads a number format name, defaulting to a plain number. */ function readNumberFormat(element, property = 'format') {
59
+ const value = element.properties[property];
60
+ return Object.values(NumberFormat).includes(value) ? value : "number";
61
+ }
62
+ /** Formats a date or an ISO 8601 date-time for a locale; a value that is not a date is returned as it was written. */ function formatDate(value, locale, withTime = false) {
63
+ const date = value instanceof Date ? value : typeof value === 'string' || typeof value === 'number' ? new Date(value) : undefined;
64
+ if (!date || Number.isNaN(date.getTime())) return typeof value === 'string' ? value : '';
65
+ try {
66
+ return new Intl.DateTimeFormat(locale, withTime ? {
67
+ dateStyle: 'medium',
68
+ timeStyle: 'short'
69
+ } : {
70
+ dateStyle: 'medium'
71
+ }).format(date);
72
+ } catch {
73
+ return date.toISOString();
74
+ }
75
+ }
76
+
77
+ export { NumberFormat, formatDate, formatNumber, isRightToLeft, readLocale, readNumberFormat };
78
+ //# sourceMappingURL=formatting.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"formatting.js","sources":["../../../foundation/formatting.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 { ExternalComponent } from '@cratis/scene.model';\n\n/** How a number is presented. */\nexport enum NumberFormat {\n Number = 'number',\n Currency = 'currency',\n Percent = 'percent',\n Compact = 'compact',\n}\n\n/**\n * The locale a component formats dates, numbers and currency in: the element's `locale`, else the document language, else the\n * runtime's. Formatting never goes through a fixed locale, so the same screen reads correctly in every one.\n */\nexport function readLocale(element: ExternalComponent): string {\n const supplied = element.properties.locale;\n if (typeof supplied === 'string' && supplied.length > 0) return supplied;\n if (typeof document !== 'undefined' && document.documentElement.lang) return document.documentElement.lang;\n return typeof navigator !== 'undefined' && navigator.language ? navigator.language : 'en';\n}\n\n/** Whether the locale reads right to left, so a component can mirror what direction-sensitive CSS cannot. */\nexport function isRightToLeft(locale: string): boolean {\n try {\n const info = new Intl.Locale(locale) as Intl.Locale & { getTextInfo?: () => { direction: string }; textInfo?: { direction: string } };\n const direction = info.getTextInfo?.().direction ?? info.textInfo?.direction;\n return direction === 'rtl';\n } catch {\n return false;\n }\n}\n\n/** Formats a number for a locale, as a plain number, currency, percent (the value is the percentage, 12.5 is 12.5%) or compact. */\nexport function formatNumber(value: number, locale: string, format: NumberFormat = NumberFormat.Number, currency = 'USD', maximumFractionDigits?: number): string {\n try {\n switch (format) {\n case NumberFormat.Currency:\n return new Intl.NumberFormat(locale, { style: 'currency', currency, ...(maximumFractionDigits === undefined ? {} : { maximumFractionDigits }) }).format(value);\n case NumberFormat.Percent:\n return new Intl.NumberFormat(locale, { style: 'percent', maximumFractionDigits: maximumFractionDigits ?? 1 }).format(value / 100);\n case NumberFormat.Compact:\n return new Intl.NumberFormat(locale, { notation: 'compact', maximumFractionDigits: maximumFractionDigits ?? 1 }).format(value);\n default:\n return new Intl.NumberFormat(locale, { maximumFractionDigits: maximumFractionDigits ?? 2 }).format(value);\n }\n } catch {\n return String(value);\n }\n}\n\n/** Reads a number format name, defaulting to a plain number. */\nexport function readNumberFormat(element: ExternalComponent, property = 'format'): NumberFormat {\n const value = element.properties[property];\n return (Object.values(NumberFormat) as string[]).includes(value as string) ? (value as NumberFormat) : NumberFormat.Number;\n}\n\n/** Formats a date or an ISO 8601 date-time for a locale; a value that is not a date is returned as it was written. */\nexport function formatDate(value: unknown, locale: string, withTime = false): string {\n const date = value instanceof Date ? value : typeof value === 'string' || typeof value === 'number' ? new Date(value) : undefined;\n if (!date || Number.isNaN(date.getTime())) return typeof value === 'string' ? value : '';\n try {\n return new Intl.DateTimeFormat(locale, withTime ? { dateStyle: 'medium', timeStyle: 'short' } : { dateStyle: 'medium' }).format(date);\n } catch {\n return date.toISOString();\n }\n}\n"],"names":["NumberFormat","readLocale","element","supplied","properties","locale","length","document","documentElement","lang","navigator","language","isRightToLeft","info","Intl","Locale","direction","getTextInfo","textInfo","formatNumber","value","format","currency","maximumFractionDigits","style","undefined","notation","String","readNumberFormat","property","Object","values","includes","formatDate","withTime","date","Date","Number","isNaN","getTime","DateTimeFormat","dateStyle","timeStyle","toISOString"],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { ComponentMetadata } from '@cratis/scene.react';
2
+ export declare const foundationComponentMetadata: Record<string, ComponentMetadata>;
3
+ //# sourceMappingURL=foundationComponentMetadata.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"foundationComponentMetadata.d.ts","sourceRoot":"","sources":["../../../foundation/foundationComponentMetadata.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,iBAAiB,EAA0B,MAAM,qBAAqB,CAAC;AAOhF,eAAO,MAAM,2BAA2B,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,CASzE,CAAC"}
@@ -0,0 +1,67 @@
1
+ import { ComponentCategory } from '@cratis/scene.model';
2
+ import { componentMetadata } from '@cratis/scene.react';
3
+ import { ComponentName } from '../ComponentName.js';
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
+ /**
8
+ * The category, icon, keywords and picker badge of every foundation component (CMP1), keyed by bare component name.
9
+ * The names are those of `ComponentName`; the metadata of the rest of the package lives in `defaultBlueprintComponentMetadata`.
10
+ */ const foundationComponentMetadata = {
11
+ [ComponentName.EmptyState]: componentMetadata('Empty state', ComponentCategory.Feedback, 'inbox', [
12
+ 'no data',
13
+ 'nothing',
14
+ 'blank slate',
15
+ 'zero state'
16
+ ]),
17
+ [ComponentName.StatCard]: componentMetadata('Stat card', ComponentCategory.DataDisplay, 'gauge', [
18
+ 'kpi',
19
+ 'metric',
20
+ 'figure',
21
+ 'number',
22
+ 'dashboard'
23
+ ]),
24
+ [ComponentName.TrendChip]: componentMetadata('Trend chip', ComponentCategory.DataDisplay, 'trending-up', [
25
+ 'delta',
26
+ 'change',
27
+ 'arrow',
28
+ 'comparison'
29
+ ]),
30
+ [ComponentName.StatusChip]: componentMetadata('Status chip', ComponentCategory.DataDisplay, 'badge-check', [
31
+ 'badge',
32
+ 'state',
33
+ 'tag',
34
+ 'label'
35
+ ]),
36
+ [ComponentName.ChartWrapper]: componentMetadata('Chart', ComponentCategory.DataDisplay, 'chart-line', [
37
+ 'graph',
38
+ 'line',
39
+ 'bar',
40
+ 'stacked',
41
+ 'donut',
42
+ 'pie',
43
+ 'funnel',
44
+ 'plot'
45
+ ]),
46
+ [ComponentName.FilterBuilder]: componentMetadata('Filter builder', ComponentCategory.Input, 'list-filter', [
47
+ 'filter',
48
+ 'query',
49
+ 'conditions',
50
+ 'and or',
51
+ 'search'
52
+ ]),
53
+ [ComponentName.ColumnChooser]: componentMetadata('Column chooser', ComponentCategory.Actions, 'columns-3', [
54
+ 'columns',
55
+ 'fields',
56
+ 'show hide',
57
+ 'table'
58
+ ]),
59
+ [ComponentName.SavedViewsMenu]: componentMetadata('Saved views menu', ComponentCategory.Actions, 'bookmark', [
60
+ 'views',
61
+ 'presets',
62
+ 'saved filters'
63
+ ])
64
+ };
65
+
66
+ export { foundationComponentMetadata };
67
+ //# sourceMappingURL=foundationComponentMetadata.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"foundationComponentMetadata.js","sources":["../../../foundation/foundationComponentMetadata.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 { ComponentCategory } from '@cratis/scene.model';\nimport { ComponentMetadata, componentMetadata as m } from '@cratis/scene.react';\nimport { ComponentName } from '../ComponentName';\n\n/**\n * The category, icon, keywords and picker badge of every foundation component (CMP1), keyed by bare component name.\n * The names are those of `ComponentName`; the metadata of the rest of the package lives in `defaultBlueprintComponentMetadata`.\n */\nexport const foundationComponentMetadata: Record<string, ComponentMetadata> = {\n [ComponentName.EmptyState]: m('Empty state', ComponentCategory.Feedback, 'inbox', ['no data', 'nothing', 'blank slate', 'zero state']),\n [ComponentName.StatCard]: m('Stat card', ComponentCategory.DataDisplay, 'gauge', ['kpi', 'metric', 'figure', 'number', 'dashboard']),\n [ComponentName.TrendChip]: m('Trend chip', ComponentCategory.DataDisplay, 'trending-up', ['delta', 'change', 'arrow', 'comparison']),\n [ComponentName.StatusChip]: m('Status chip', ComponentCategory.DataDisplay, 'badge-check', ['badge', 'state', 'tag', 'label']),\n [ComponentName.ChartWrapper]: m('Chart', ComponentCategory.DataDisplay, 'chart-line', ['graph', 'line', 'bar', 'stacked', 'donut', 'pie', 'funnel', 'plot']),\n [ComponentName.FilterBuilder]: m('Filter builder', ComponentCategory.Input, 'list-filter', ['filter', 'query', 'conditions', 'and or', 'search']),\n [ComponentName.ColumnChooser]: m('Column chooser', ComponentCategory.Actions, 'columns-3', ['columns', 'fields', 'show hide', 'table']),\n [ComponentName.SavedViewsMenu]: m('Saved views menu', ComponentCategory.Actions, 'bookmark', ['views', 'presets', 'saved filters']),\n};\n"],"names":["foundationComponentMetadata","ComponentName","EmptyState","m","ComponentCategory","Feedback","StatCard","DataDisplay","TrendChip","StatusChip","ChartWrapper","FilterBuilder","Input","ColumnChooser","Actions","SavedViewsMenu"],"mappings":";;;;AAAA;AACA;AAMA;;;UAIaA,2BAAAA,GAAiE;IAC1E,CAACC,aAAAA,CAAcC,UAAU,GAAGC,kBAAE,aAAA,EAAeC,iBAAAA,CAAkBC,QAAQ,EAAE,OAAA,EAAS;AAAC,QAAA,SAAA;AAAW,QAAA,SAAA;AAAW,QAAA,aAAA;AAAe,QAAA;AAAa,KAAA,CAAA;IACrI,CAACJ,aAAAA,CAAcK,QAAQ,GAAGH,kBAAE,WAAA,EAAaC,iBAAAA,CAAkBG,WAAW,EAAE,OAAA,EAAS;AAAC,QAAA,KAAA;AAAO,QAAA,QAAA;AAAU,QAAA,QAAA;AAAU,QAAA,QAAA;AAAU,QAAA;AAAY,KAAA,CAAA;IACnI,CAACN,aAAAA,CAAcO,SAAS,GAAGL,kBAAE,YAAA,EAAcC,iBAAAA,CAAkBG,WAAW,EAAE,aAAA,EAAe;AAAC,QAAA,OAAA;AAAS,QAAA,QAAA;AAAU,QAAA,OAAA;AAAS,QAAA;AAAa,KAAA,CAAA;IACnI,CAACN,aAAAA,CAAcQ,UAAU,GAAGN,kBAAE,aAAA,EAAeC,iBAAAA,CAAkBG,WAAW,EAAE,aAAA,EAAe;AAAC,QAAA,OAAA;AAAS,QAAA,OAAA;AAAS,QAAA,KAAA;AAAO,QAAA;AAAQ,KAAA,CAAA;IAC7H,CAACN,aAAAA,CAAcS,YAAY,GAAGP,kBAAE,OAAA,EAASC,iBAAAA,CAAkBG,WAAW,EAAE,YAAA,EAAc;AAAC,QAAA,OAAA;AAAS,QAAA,MAAA;AAAQ,QAAA,KAAA;AAAO,QAAA,SAAA;AAAW,QAAA,OAAA;AAAS,QAAA,KAAA;AAAO,QAAA,QAAA;AAAU,QAAA;AAAO,KAAA,CAAA;IAC3J,CAACN,aAAAA,CAAcU,aAAa,GAAGR,kBAAE,gBAAA,EAAkBC,iBAAAA,CAAkBQ,KAAK,EAAE,aAAA,EAAe;AAAC,QAAA,QAAA;AAAU,QAAA,OAAA;AAAS,QAAA,YAAA;AAAc,QAAA,QAAA;AAAU,QAAA;AAAS,KAAA,CAAA;IAChJ,CAACX,aAAAA,CAAcY,aAAa,GAAGV,kBAAE,gBAAA,EAAkBC,iBAAAA,CAAkBU,OAAO,EAAE,WAAA,EAAa;AAAC,QAAA,SAAA;AAAW,QAAA,QAAA;AAAU,QAAA,WAAA;AAAa,QAAA;AAAQ,KAAA,CAAA;IACtI,CAACb,aAAAA,CAAcc,cAAc,GAAGZ,kBAAE,kBAAA,EAAoBC,iBAAAA,CAAkBU,OAAO,EAAE,UAAA,EAAY;AAAC,QAAA,OAAA;AAAS,QAAA,SAAA;AAAW,QAAA;AAAgB,KAAA;AACtI;;"}
@@ -0,0 +1,6 @@
1
+ import { BindingSourceKind, ComponentDescriptor, PropertyDescriptor } from '@cratis/scene.model';
2
+ export declare const bindable: BindingSourceKind[];
3
+ export declare const list: (path: string, label: string, group: string, itemLabel: string, properties: PropertyDescriptor[], description?: string) => PropertyDescriptor;
4
+ export declare const standardStateProperties: PropertyDescriptor[];
5
+ export declare const foundationDescriptors: ComponentDescriptor[];
6
+ //# sourceMappingURL=foundationDescriptors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"foundationDescriptors.d.ts","sourceRoot":"","sources":["../../../foundation/foundationDescriptors.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,kBAAkB,EAAyC,MAAM,qBAAqB,CAAC;AAYxI,eAAO,MAAM,QAAQ,qBAAsG,CAAC;AAiB5H,eAAO,MAAM,IAAI,SAAU,MAAM,SAAS,MAAM,SAAS,MAAM,aAAa,MAAM,cAAc,kBAAkB,EAAE,gBAAgB,MAAM,KAAG,kBACoC,CAAC;AAMlL,eAAO,MAAM,uBAAuB,EAAE,kBAAkB,EAkBvD,CAAC;AAOF,eAAO,MAAM,qBAAqB,EAAE,mBAAmB,EA0ItD,CAAC"}