@dataworkz/crystal 0.1.0-beta.0 → 0.1.0-beta.10

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 (43) hide show
  1. package/CHANGELOG.md +151 -13
  2. package/README.md +6 -0
  3. package/fesm2022/dataworkz-crystal-icons.mjs +32 -322
  4. package/fesm2022/dataworkz-crystal-icons.mjs.map +1 -1
  5. package/fesm2022/dataworkz-crystal-markdown.mjs +1 -1
  6. package/fesm2022/dataworkz-crystal-markdown.mjs.map +1 -1
  7. package/fesm2022/dataworkz-crystal-primeng.mjs +31 -5
  8. package/fesm2022/dataworkz-crystal-primeng.mjs.map +1 -1
  9. package/fesm2022/dataworkz-crystal.mjs +2635 -257
  10. package/fesm2022/dataworkz-crystal.mjs.map +1 -1
  11. package/icons/index.d.ts +33 -97
  12. package/icons/svg/files/csv.svg +0 -1
  13. package/icons/svg/files/generic.svg +0 -1
  14. package/icons/svg/files/multimedia.svg +0 -1
  15. package/icons/svg/glyphs/agentBuilder.svg +1 -1
  16. package/icons/svg/glyphs/notesPad.svg +1 -1
  17. package/icons/svg/glyphs/panelCollapse.svg +1 -1
  18. package/icons/svg/glyphs/panelExpand.svg +1 -1
  19. package/icons/svg/glyphs/play.svg +1 -1
  20. package/icons/svg/glyphs/robot.svg +1 -1
  21. package/icons/svg/glyphs/sidebarCollapse.svg +1 -1
  22. package/icons/svg/glyphs/sidebarExpand.svg +1 -1
  23. package/icons/svg/glyphs/tagFilled.svg +1 -1
  24. package/icons/svg/glyphs/testShield.svg +1 -1
  25. package/icons/svg/storage/generic.svg +0 -1
  26. package/icons/svg/storage/legacy/microsoft-mail.svg +0 -1
  27. package/icons/svg/storage/local/microsoft-mail.svg +0 -1
  28. package/index.d.ts +1207 -68
  29. package/package.json +5 -7
  30. package/primeng/index.d.ts +45 -5
  31. package/styles/base.css +4 -4
  32. package/styles/components/button.css +3 -0
  33. package/styles/components/content.css +89 -91
  34. package/styles/components/data.css +24 -1
  35. package/styles/components/form.css +116 -13
  36. package/styles/components/navigation.css +31 -1
  37. package/styles/components/overlay.css +16 -1
  38. package/styles/components/surface.css +38 -2
  39. package/styles/components/toast.css +1 -1
  40. package/styles/crystal-no-fonts.css +3 -2
  41. package/styles/icons.css +6 -0
  42. package/styles/tokens/primitives.css +1 -3
  43. package/styles/tokens/semantic-dark.css +1 -1
package/CHANGELOG.md CHANGED
@@ -2,30 +2,168 @@
2
2
 
3
3
  All notable changes to this package. Versions follow [semver](https://semver.org); betas may still change the API.
4
4
 
5
+ ## 0.1.0-beta.10 — 2026-11-05
6
+
7
+ ### Added
8
+ - `dw-accordion` / `dw-accordion-panel` (`DW_ACCORDION`): one or several open panels, `flush` and `card` variants, rich
9
+ headers (`dwAccordionHeader`) with controls that don't toggle (`dwAccordionHeaderAction`), lazy content
10
+ (`dwAccordionContent`), `opened` / `closed` once the animation is over.
11
+ - `dw-stepper`: a wizard's step list (done / current / upcoming), `linear`, `md` / `sm`, `framed`, `doneIcon`.
12
+ Crystal-native.
13
+ - `dw-autocomplete`: a form control that suggests as you type, free text or `forceSelection`, an item template, the
14
+ list as wide as the field by default.
15
+ - `dw-slider`: a number form control between `min` and `max`.
16
+ - `dw-splitter`: resizable panes with sizes, minimum sizes and remembered sizes (compatible with what `p-splitter`
17
+ saved), on `dw-resizer`.
18
+ - `dw-table`: `DwSortMeta`, `DwSortEvent` and `DwSortChange` type `multiSortMeta`, `sortFunction` and `sortChange`
19
+ (they were PrimeNG's types, or `unknown`). Same shapes.
20
+
21
+ ## 0.1.0-beta.9 — 2026-11-05
22
+
23
+ ### Added
24
+ - `dw-tree` `size="sm"`: compact rows (a smaller toggle, padding and type), for a sidebar or a narrow panel.
25
+ - `dw-tree` `marker`: an accent bar at the start of the selected row, as `dw-nav-list`'s `marker`.
26
+
27
+ ## 0.1.0-beta.8 — 2026-11-05
28
+
29
+ ### Added
30
+ - `dw-tree` and `DwTreeNode`: a tree over PrimeNG's Tree, selecting one node, several, or checkboxes (a parent checks
31
+ its children), with children loaded when a node opens, a node template (`dwTreeNode`), `scrollHeight`, and a
32
+ `contextMenu`. It has no box of its own; `framed` draws one. Replaces PrimeNG's Tree and ContextMenu in apps.
33
+ - `dw-menu` `openAt(event, context?)`: opens the menu as a context menu, at the pointer and inside the viewport, its
34
+ commands receiving `context` (what was right-clicked).
35
+
36
+ ## 0.1.0-beta.7 — 2026-11-05
37
+
38
+ ### Added
39
+ - `dw-date-picker` `flush`: an inline calendar without its own border, fill, radius or padding, so it sits on a popover's
40
+ or panel's surface. Screens no longer reach into the calendar's PrimeNG classes for it.
41
+
42
+ ### Fixed
43
+ - An inline `dw-date-picker` with `fluid` fills its container; it kept the calendar's own width. A field picker, and an
44
+ inline one without `fluid`, are unchanged.
45
+
46
+ ## 0.1.0-beta.6 — 2026-11-05
47
+
48
+ ### Added
49
+ - `dw-date-picker`: date, date-time (to the second) and range picking, as a field or an inline calendar, on the shared
50
+ form-control base (ngModel, reactive forms, `[(value)]`). Replaces PrimeNG's DatePicker in apps.
51
+ - `dw-chart`: a chart.js chart (`line`, `bar`, `doughnut`…) over PrimeNG's Chart, with chart.js's own `data` and
52
+ `options`. A new `type`, size or `plugins` builds the chart again, as new `data` or `options` do.
53
+ - chart.js is a crystal dependency, so an app drops it from its own package.json.
54
+
55
+ ### Changed
56
+ - The form controls no longer write the user's own change back into their PrimeNG control (as ngModel doesn't). The
57
+ control has the value already; a date picker written its own value turned its calendar to that date's month.
58
+
59
+ ## 0.1.0-beta.5 — 2026-11-04
60
+
61
+ ### Added
62
+ - `dwTooltipVariant="preview"`: a long value shown whole, up to 720 × 340px, then scrolled (line breaks kept). Pair it
63
+ with `dwTooltipInteractive` so the pointer can scroll it.
64
+ - `dw-select` / `dw-multiselect` `baseZIndex`: stacks the list above a layer that sets its own z-index (as dw-dialog /
65
+ dw-drawer / dw-popover's `baseZIndex`).
66
+ - `dw-checkbox` `option`: one box of a set that fills one array (ticked while the array holds the option; a click adds
67
+ or removes it). `DwCheckboxComponent` is generic (`<T = boolean>`); a plain checkbox is unchanged.
68
+ - `DW_PRIMENG_Z_INDEX`, the z-index bases `provideCrystalPrimeNG()` installs.
69
+ - `styles/icons.css`: the PrimeIcons font on its own, for an app that imports crystal's styles file by file (crystal.css
70
+ and crystal-no-fonts.css import it). With it, an app drops primeicons from its own package.json and build.
71
+
72
+ ### Changed
73
+ - Tooltips stack from a 5000 base instead of PrimeNG's 1100, so they also clear layers that set their own z-index (they
74
+ already cleared PrimeNG's own overlays). An app's `zIndex` setting still wins. The `code` variant's CSS `z-index`
75
+ (which PrimeNG's inline z-index always overrode) is gone.
76
+
77
+ ## 0.1.0-beta.4 — 2026-11-04
78
+
79
+ ### Added
80
+ - `dw-select` / `dw-multiselect` `open()` and `close()`: open the list from code (an editable select whose text opens it).
81
+ - `[dwTooltipInteractive]`: the tooltip stays open while the pointer moves onto it, so its text can be copied.
82
+
83
+ ### Fixed
84
+ - `dw-field` gives a `dw-select`, `dw-multiselect` or `dw-number-input` its full width, as it did the PrimeNG controls.
85
+ - `dw-switch`, `dw-radio`, `dw-number-input` and `dw-multiselect` no longer take focus when a page opens (and scroll it to
86
+ themselves): PrimeNG's AutoFocus put `autofocus="true"` on their input unless told `false`.
87
+ - The form controls drive their PrimeNG control without subscribing to PrimeNG's own signals: a write that changed one
88
+ of them could have re-run the write without end.
89
+
90
+ ## 0.1.0-beta.3 — 2026-11-04
91
+
92
+ The first step of taking PrimeNG out of apps (docs/PRIMENG-REMOVAL.md): crystal's own form controls, and crystal owns
93
+ PrimeNG.
94
+
95
+ ### Breaking
96
+ - `primeng`, `@primeng/themes` and `primeicons` are crystal **dependencies**, no longer peers: an app removes them from
97
+ its own `package.json` (and PrimeIcons' CSS from its build: crystal's stylesheet loads it).
98
+
99
+ ### Added
100
+ - `dwInput` on `<input>` / `<textarea>` (`DW_INPUT`): `size` (`sm|md|lg`), `fluid`, `invalid`, `autoResize`.
101
+ - `[dwTooltip]`: `dwTooltipPosition` (`top` by default), `dwTooltipDelay`, `dwTooltipVariant`
102
+ (`multiline|code|error|toolbar`), `dwTooltipDisabled`.
103
+ - `dw-select` (+ `dwSelectOption`, `dwSelectValue`, `dwSelectFooter` templates) and `dw-multiselect`.
104
+ - `dw-checkbox`, `dw-radio`, `dw-switch` (`xs|sm|md`), `dw-number-input`.
105
+ - All of them work with ngModel, reactive forms or `[(value)]`, show invalid once touched or dirty, emit `changed` for
106
+ the user's change only, and keep the look of the PrimeNG controls they replace. `DwFormControl` is their base.
107
+ - `dw-icon pi="<name>"`: a PrimeIcons glyph, typed by `DwPrimeIcon` (from the installed font); `spin` and `label` on
108
+ every dw-icon.
109
+
110
+ ### Changed
111
+ - `dw-icon`'s `name` is optional (give `name` or `pi`).
112
+ - `dw-field` docs and every crystal story use crystal controls; `dw-field` keeps a `dw-switch` / `dw-checkbox` /
113
+ `dw-radio` at its own width, as it did PrimeNG's.
114
+
115
+ ## 0.1.0-beta.2 — 2026-11-04
116
+
117
+ ### Fixed
118
+ - Small selects get small options wherever their list is appended: `provideCrystalPrimeNG()` now adds
119
+ `dw-select-panel--sm` to the overlay of every `p-select` / `p-multiselect` with `size="small"`, through PrimeNG's
120
+ pass-through (`DW_PRIMENG_PT`, exported). Lists appended to `<body>` used to keep the 14px rows; screens no longer
121
+ set the class by hand. An app's own `pt` settings are merged over crystal's.
122
+ - A selected `dw-icon-button` with `variant="danger"` stays danger red instead of switching to the accent (e.g. a
123
+ "not helpful" rating). Every other variant's selected state is unchanged.
124
+
125
+ ## 0.1.0-beta.1 — 2026-11-04
126
+
127
+ The package is now product-neutral: no app type ids, app-only CSS or app validator messages ship in it. An app maps
128
+ its own vocabulary onto crystal through two new provider hooks.
129
+
130
+ ### Breaking
131
+ - Logo lookups are by icon key only. `getToolIconPath`, `resolveToolIconKey`, `getStorageIconPath`,
132
+ `resolveStorageIconKey`, `BUILT_IN_TOOL_ICON`, `AGENT_NODE_ICON` and `GENERIC_STORAGE_ICON_LEGACY` are removed; use
133
+ `toolIcon(key)` and `storageIcon(key, { set })`. Type-id → key maps belong to the app.
134
+ - `dw-entity-icon` `kind="tool"` / `kind="storage"` read `type` as an icon key (`snowflake`, `s3`…), unless the app
135
+ provides a resolver (below).
136
+ - The chat-message, chat-composer and citation-chip CSS is removed from `styles/` (it was app-specific).
137
+ - `DW_FIELD_MESSAGES` holds Angular's built-in validators only (`required`, `requiredTrue`, `email`, `pattern`, `min`,
138
+ `max`, `minlength`, `maxlength`). Messages for an app's own validators come from `provideCrystalFieldMessages()`.
139
+
140
+ ### Added
141
+ - `TOOL_ICON_KEYS`, `isToolIconKey()`, `toolIcon()`, `GENERIC_TOOL_ICON`, `storageIconKeys()`, `storageIcon()`, and the
142
+ `ToolIconKey` / `StorageIconKey` types (`@dataworkz/crystal/icons`).
143
+ - `provideCrystalIconResolvers({ tool, storage })`: map an app's type ids to icon keys for `dw-entity-icon`.
144
+ - `provideCrystalFieldMessages({ … })`: messages for an app's own validator keys (a per-field `messages` input still
145
+ wins).
146
+
147
+ ### Changed
148
+ - Comments, examples and the raw `icons/svg/` files carry no internal references; shipped SVGs have no comments.
149
+ - The package check fails a build that ships app vocabulary, source maps included.
150
+
5
151
  ## 0.1.0-beta.0 — 2026-11-04
6
152
 
7
- First release: the Dataworkz core UI, moved out of dataworkz-ui (`0b7c763c`) into its own package.
153
+ First release.
8
154
 
9
155
  ### Added
10
156
  - 49 `dw-*` components and directives (buttons, menus, badges, tags, chips, cards, sections, tabs, nav list, dialogs,
11
- drawers, popovers, tables, fields, file dropzone, toasts…), with the same selectors, inputs and outputs as dataworkz-ui.
157
+ drawers, popovers, tables, fields, file dropzone, toasts…).
12
158
  - `provideCrystal({ theme })` and `ThemeService` (light / dark on `data-theme`), `provideCrystalPrimeNG()` and `DwPreset`
13
159
  (`@dataworkz/crystal/primeng`).
14
160
  - Toasts: `DwToastService` owns the stack (`success / info / warning / error`, `dismiss`, `clear`, `toasts`), rendered by
15
- `<dw-toast-host>` in today's look.
16
- - Icons: every Dataworkz icon is an `.svg` file, inlined (no asset URLs): glyphs via `dw-icon` / `dwi-<name>`, tool /
17
- storage / file-type logos as data URIs (`@dataworkz/crystal/icons`, raw files under `icons/svg/`).
161
+ `<dw-toast-host>`.
162
+ - Icons: every icon is an `.svg` file, inlined (no asset URLs): glyphs via `dw-icon` / `dwi-<name>`, tool / storage /
163
+ file-type logos as data URIs (`@dataworkz/crystal/icons`, raw files under `icons/svg/`).
18
164
  `provideCrystalIcons()` / `DwIconRegistry` register an app's own icons by name.
19
165
  - Theme CSS (`styles/crystal.css`, `crystal-no-fonts.css`) with Inter and IBM Plex Mono bundled (OFL); nothing is
20
166
  loaded from a font service or CDN.
21
167
  - `installCrystalHostTheme()` themes pages crystal doesn't own (federated custom elements).
22
168
  - Token helpers `dwVar`, `cssVar`, `chartPalette` (`@dataworkz/crystal/tokens`); `dw-code-block`, `dw-markdown`
23
169
  (`@dataworkz/crystal/markdown`, optional `ngx-markdown`).
24
-
25
- ### Changed (compared with the copies in dataworkz-ui)
26
- - `DwMenuItem.privilege` is gone: hide items with `visible` (e.g. `visible: auth.hasPrivilege('x')`).
27
- - The icon lookups (`getToolIconPath`, `getStorageIconPath`, `fileIconByExtension`) return data URIs instead of asset paths.
28
- - `DW_ICON_NAMES` is alphabetical.
29
- - `installElementTheme()` / `DwElementThemeComponent` are replaced by `installCrystalHostTheme()`; element hosts take the
30
- `dw-element` class for the theme font.
31
- - `dw-tile` keeps a real space between its count and unit (screen readers read "3 connections").
package/README.md CHANGED
@@ -33,6 +33,12 @@ export const appConfig = {
33
33
  - **Toasts:** `inject(DwToastService).success('Saved')`, `.error('Failed', { sticky: true })`, `.dismiss(id)`, `.clear()`.
34
34
  - **Your own icons:** `provideCrystalIcons({ rocket: rocketSvg })` (markup strings, e.g. `import rocketSvg from './rocket.svg?raw'`;
35
35
  any name not starting with `dw`), then `<dw-icon name="rocket" />` or `icon="rocket"`.
36
+ - **Logos:** `toolIcon('snowflake')`, `storageIcon('s3')`, `storageIcon('postgres', { set: 'sources' })` (data URIs;
37
+ `TOOL_ICON_KEYS` / `storageIconKeys()` list the keys). `<dw-entity-icon kind="tool" type="snowflake" />` reads `type`
38
+ as a key; to pass your own type ids instead, map them once:
39
+ `provideCrystalIconResolvers({ tool: (type) => myToolKeys[type], storage: (type) => myStorageKeys[type] })`.
40
+ - **Field messages:** `dw-field` knows Angular's built-in validators. Add messages for your own validator keys with
41
+ `provideCrystalFieldMessages({ duplicate: 'This name already exists' })` (a field's `messages` input still wins).
36
42
  - **Federated custom elements on a page you don't own:** `provideCrystal({ theme: { apply: false } })`, call
37
43
  `installCrystalHostTheme()` in the element's bootstrap, and put the `dw-element` class on the element host.
38
44
  `installCrystalHostTheme({ fonts: false })` if the page already loads Inter / IBM Plex Mono.
@@ -267,339 +267,49 @@ function icon(name, size = '1em', color = 'currentColor') {
267
267
  return DW_GLYPH_SVGS[name].replace('<svg', `<svg width="${size}" height="${size}"`).replace(/currentColor/g, color);
268
268
  }
269
269
 
270
- /** Shown when a typeId matches no known tool family. */
270
+ /** Every tool icon key, from the files in `icons/svg/tools/`. */
271
+ const TOOL_ICON_KEYS = Object.keys(DW_LOGO_URIS)
272
+ .filter((path) => path.startsWith('tools/') && path !== 'tools/generic')
273
+ .map((path) => path.slice('tools/'.length));
274
+ /** Shown for a tool without its own artwork. */
271
275
  const GENERIC_TOOL_ICON = DW_LOGO_URIS['tools/generic'];
272
- /** Built-in Dataworkz tools, identified by a `dz-` tool id prefix. */
273
- const BUILT_IN_TOOL_ICON = DW_LOGO_URIS['tools/built-in'];
274
- /** Agent nodes inside dependency / reference trees. */
275
- const AGENT_NODE_ICON = DW_LOGO_URIS['tools/agent'];
276
- /**
277
- * Backend `typeId` / `subType` values (lowercased) -> canonical family.
278
- * Also accepts the UI filter keys (`dataset-query`, `built-in`, ...) so filter
279
- * rows and tool rows resolve through the same table.
280
- */
281
- const TYPE_ID_TO_KEY = {
282
- 'dw-data-api': 'dataset-read',
283
- dataset: 'dataset-read',
284
- 'dataset-query': 'dataset-read',
285
- 'dw-data-write-api': 'dataset-write',
286
- 'dataset-write': 'dataset-write',
287
- qna: 'rag-app',
288
- 'qna-search': 'rag-app',
289
- 'rag-app': 'rag-app',
290
- 'mongodb.query': 'mongodb',
291
- mongodb: 'mongodb',
292
- graphql: 'graphql',
293
- snowflake: 'snowflake',
294
- 'rest-api': 'rest-api',
295
- llm: 'llm',
296
- 'relational-db': 'relational-db',
297
- jdbc: 'relational-db',
298
- composite: 'workflow',
299
- workflow: 'workflow',
300
- 'call-agent': 'call-agent',
301
- 'dw-docstore-finddocs-api': 'docstore',
302
- 'dw-docstore-getdoc-api': 'docstore',
303
- 'dw-docstore-fetchdoccon-api': 'docstore',
304
- // Custom metric tools. Only built-in rows carry these types, so they share the built-in
305
- // mark - also on surfaces that pass the typeId without the dz- tool id.
306
- 'dw-metric-write-api': 'built-in',
307
- 'dw-metric-read-api': 'built-in',
308
- 'dw-metric-list-api': 'built-in',
309
- agent: 'agent',
310
- 'built-in': 'built-in',
311
- // Closed-loop system tools call a REST endpoint through a stored connection, so they reuse the
312
- // rest-api family. Both the saved typeId and the create-route segment resolve here. A branded
313
- // system that gains its own artwork adds a ToolIconKey; until then one row each is enough.
314
- 'generic-close-loop-system': 'rest-api',
315
- 'generic-saas': 'rest-api',
316
- };
317
- /**
318
- * The canonical icon per tool family. Bare glyphs — see the framing note above.
319
- *
320
- * `docstore` and `built-in` deliberately share the Dataworkz document mark: the
321
- * docstore APIs *are* built-in tools, and the two were only ever distinguished
322
- * by which folder a surface happened to read from.
323
- */
324
- const TOOL_ICONS = {
325
- 'dataset-read': DW_LOGO_URIS['tools/dataset-read'],
326
- 'dataset-write': DW_LOGO_URIS['tools/dataset-write'],
327
- 'rag-app': DW_LOGO_URIS['tools/rag-app'],
328
- mongodb: DW_LOGO_URIS['tools/mongodb'],
329
- graphql: DW_LOGO_URIS['tools/graphql'],
330
- snowflake: DW_LOGO_URIS['tools/snowflake'],
331
- 'rest-api': DW_LOGO_URIS['tools/rest-api'],
332
- llm: DW_LOGO_URIS['tools/llm'],
333
- 'relational-db': DW_LOGO_URIS['tools/relational-db'],
334
- workflow: DW_LOGO_URIS['tools/workflow'],
335
- 'call-agent': DW_LOGO_URIS['tools/call-agent'],
336
- docstore: BUILT_IN_TOOL_ICON,
337
- agent: AGENT_NODE_ICON,
338
- 'built-in': BUILT_IN_TOOL_ICON,
339
- };
340
- const has = (text, needle) => text.includes(needle);
341
- const isDocStore = (text) => has(text, 'docstore') || has(text, 'doc store');
276
+ function isToolIconKey(key) {
277
+ return !!key && TOOL_ICON_KEYS.includes(key);
278
+ }
342
279
  /**
343
- * Ordered loose rules for callers that only have free text (a tool name, a
344
- * label, several fields joined together) instead of a clean typeId. Order
345
- * matters: the first match wins.
280
+ * The tool icon (a data URI) for a key, e.g. `toolIcon('snowflake')`, or `fallback` for an unknown key.
281
+ * Keys are crystal's artwork names; map your own tool types to them (e.g. with `provideCrystalIconResolvers()`).
346
282
  */
347
- const FUZZY_RULES = [
348
- {
349
- key: 'dataset-write',
350
- test: text => text === 'dw-data-write-api' ||
351
- (has(text, 'dataset') && has(text, 'write')) ||
352
- (isDocStore(text) && has(text, 'write')),
353
- },
354
- {
355
- key: 'dataset-read',
356
- test: text => text === 'dw-data-api' ||
357
- (has(text, 'dataset') && (has(text, 'read') || has(text, 'query'))) ||
358
- (isDocStore(text) && (has(text, 'read') || has(text, 'query'))),
359
- },
360
- { key: 'dataset-read', test: isDocStore },
361
- {
362
- key: 'rag-app',
363
- test: text => text === 'qna' || text === 'qna-search' || text === 'rag-app' || has(text, 'rag'),
364
- },
365
- {
366
- key: 'mongodb',
367
- test: text => text === 'mongodb.query' || text === 'mongodb' || has(text, 'mongo'),
368
- },
369
- { key: 'graphql', test: text => text === 'graphql' || has(text, 'graph') },
370
- { key: 'snowflake', test: text => has(text, 'snowflake') },
371
- { key: 'rest-api', test: text => text === 'rest-api' || has(text, 'rest') },
372
- { key: 'llm', test: text => has(text, 'llm') },
373
- {
374
- key: 'relational-db',
375
- test: text => text === 'relational-db' || text === 'jdbc' || has(text, 'relational'),
376
- },
377
- {
378
- key: 'workflow',
379
- test: text => text === 'composite' || text === 'workflow' || has(text, 'workflow'),
380
- },
381
- { key: 'call-agent', test: text => text === 'call-agent' || has(text, 'call agent') },
382
- ];
383
- /** Canonical family for a typeId / subType, or `null` when unknown. */
384
- function resolveToolIconKey(typeId, options = {}) {
385
- const normalized = String(typeId ?? '')
386
- .trim()
387
- .toLowerCase();
388
- if (!normalized)
389
- return null;
390
- if (options.fuzzy) {
391
- return FUZZY_RULES.find(rule => rule.test(normalized))?.key ?? null;
392
- }
393
- return TYPE_ID_TO_KEY[normalized] ?? null;
394
- }
395
- /** Icon (a data URI) for a tool type. The only place a tool icon is decided. (The name is kept from when it returned an asset path.) */
396
- function getToolIconPath(typeId, options = {}) {
397
- const toolId = String(options.toolId ?? '')
398
- .trim()
399
- .toLowerCase();
400
- if (toolId.startsWith('dz-'))
401
- return TOOL_ICONS['built-in'];
402
- const key = resolveToolIconKey(typeId, options);
403
- if (key)
404
- return TOOL_ICONS[key];
405
- return options.fallback ?? GENERIC_TOOL_ICON;
283
+ function toolIcon(key, fallback = GENERIC_TOOL_ICON) {
284
+ return isToolIconKey(key) ? DW_LOGO_URIS[`tools/${key}`] : fallback;
406
285
  }
407
286
 
408
- /** Shown for a storage type the set has no artwork for. */
287
+ /** Shown for a storage type the set has no artwork for (the `local` and `legacy` sets). */
409
288
  const GENERIC_STORAGE_ICON = DW_LOGO_URIS['storage/generic'];
410
- /** The legacy set's generic icon: the same artwork as {@link GENERIC_STORAGE_ICON} (they were twin files). */
411
- const GENERIC_STORAGE_ICON_LEGACY = DW_LOGO_URIS['storage/generic'];
412
- /** Fallback for collection rows, which read better as a generic datastore. */
289
+ /** A generic datastore, e.g. for collection rows. */
413
290
  const GENERIC_COLLECTION_ICON = DW_LOGO_URIS['storage/collection'];
414
- /**
415
- * Raw `storageType` values (lowercased) -> canonical family. Closed-loop SaaS
416
- * connectors are listed explicitly rather than prefix-stripped, because
417
- * `google` (cloud storage) and `closedloop_google` (Sheets) are different logos.
418
- */
419
- const STORAGE_TYPE_TO_KEY = {
420
- s3: 's3',
421
- azure: 'azure',
422
- google: 'google-cloud',
423
- gcp: 'google-cloud',
424
- gcs: 'google-cloud',
425
- hdfs: 'hdfs',
426
- snowflake: 'snowflake',
427
- bigquery: 'bigquery',
428
- databricks: 'databricks',
429
- datastax: 'datastax',
430
- relational_mysql: 'mysql',
431
- relational_postgres: 'postgres',
432
- relational_cockroach: 'cockroach',
433
- relational_oracle: 'oracle',
434
- graph_oracle: 'oracle',
435
- relational_mariadb: 'mariadb',
436
- relational_db2: 'db2',
437
- relational_microsoft: 'sqlserver',
438
- mongodb: 'mongodb',
439
- elastic_search: 'elastic',
440
- aerospike: 'aerospike',
441
- redshift: 'redshift',
442
- kafka: 'kafka',
443
- pinecone: 'pinecone',
444
- neo4j: 'neo4j',
445
- opensearch: 'opensearch',
446
- couchbase: 'couchbase',
447
- salesforce: 'salesforce',
448
- closedloop_salesforce: 'salesforce',
449
- marketo: 'marketo',
450
- closedloop_marketo: 'marketo',
451
- hubspot: 'hubspot',
452
- closedloop_hubspot: 'hubspot',
453
- jira: 'jira',
454
- closedloop_jira: 'jira',
455
- zoom: 'zoom',
456
- closedloop_zoom: 'zoom',
457
- outreach: 'outreach',
458
- closedloop_outreach: 'outreach',
459
- pendo: 'pendo',
460
- closedloop_pendo: 'pendo',
461
- closedloop_google: 'google-sheets',
462
- storagebridge: 'storagebridge',
463
- closedloop_storagebridge: 'storagebridge',
464
- onedrive: 'onedrive',
465
- sharepoint: 'sharepoint',
466
- googledrive: 'googledrive',
467
- nas: 'nas',
468
- upload: 'upload',
469
- microsoftmail: 'microsoft-mail',
470
- closedloop_microsoftmail: 'microsoft-mail',
471
- filestream: 'filestream',
472
- closedloop_filestream: 'filestream',
473
- broadcomclarity: 'broadcom-clarity',
474
- closedloop_broadcomclarity: 'broadcom-clarity',
475
- };
476
- /**
477
- * dataworkz-ui's own artwork. File sources (onedrive, sharepoint, nas, upload…),
478
- * cockroach and the closed-loop-only connectors have no local art — those fall
479
- * through to the generic icon, as they did before.
480
- */
481
- const LOCAL_ICONS = {
482
- s3: DW_LOGO_URIS['storage/local/s3'],
483
- azure: DW_LOGO_URIS['storage/local/azure'],
484
- 'google-cloud': DW_LOGO_URIS['storage/local/google-cloud'],
485
- hdfs: DW_LOGO_URIS['storage/local/hdfs'],
486
- snowflake: DW_LOGO_URIS['storage/local/snowflake'],
487
- bigquery: DW_LOGO_URIS['storage/local/bigquery'],
488
- databricks: DW_LOGO_URIS['storage/local/databricks'],
489
- datastax: DW_LOGO_URIS['storage/local/datastax'],
490
- mysql: DW_LOGO_URIS['storage/local/mysql'],
491
- postgres: DW_LOGO_URIS['storage/local/postgres'],
492
- oracle: DW_LOGO_URIS['storage/local/oracle'],
493
- mariadb: DW_LOGO_URIS['storage/local/mariadb'],
494
- db2: DW_LOGO_URIS['storage/local/db2'],
495
- sqlserver: DW_LOGO_URIS['storage/local/sqlserver'],
496
- mongodb: DW_LOGO_URIS['storage/local/mongodb'],
497
- elastic: DW_LOGO_URIS['storage/local/elastic'],
498
- aerospike: DW_LOGO_URIS['storage/local/aerospike'],
499
- redshift: DW_LOGO_URIS['storage/local/redshift'],
500
- kafka: DW_LOGO_URIS['storage/local/kafka'],
501
- pinecone: DW_LOGO_URIS['storage/local/pinecone'],
502
- neo4j: DW_LOGO_URIS['storage/local/neo4j'],
503
- opensearch: DW_LOGO_URIS['storage/local/opensearch'],
504
- couchbase: DW_LOGO_URIS['storage/local/couchbase'],
505
- salesforce: DW_LOGO_URIS['storage/local/salesforce'],
506
- marketo: DW_LOGO_URIS['storage/local/marketo'],
507
- hubspot: DW_LOGO_URIS['storage/local/hubspot'],
508
- jira: DW_LOGO_URIS['storage/local/jira'],
509
- zoom: DW_LOGO_URIS['storage/local/zoom'],
510
- outreach: DW_LOGO_URIS['storage/local/outreach'],
511
- pendo: DW_LOGO_URIS['storage/local/pendo'],
512
- 'google-sheets': DW_LOGO_URIS['storage/local/google-sheets'],
513
- 'microsoft-mail': DW_LOGO_URIS['storage/local/microsoft-mail'],
514
- };
515
- /**
516
- * dataworkz-web's artwork — the widest set, and the only one carrying
517
- * file-source and closed-loop-only artwork. Some logos differ from `local`
518
- * (e.g. sqlserver, onedrive).
519
- */
520
- const LEGACY_ICONS = {
521
- s3: DW_LOGO_URIS['storage/legacy/s3'],
522
- azure: DW_LOGO_URIS['storage/legacy/azure'],
523
- 'google-cloud': DW_LOGO_URIS['storage/legacy/google-cloud'],
524
- hdfs: DW_LOGO_URIS['storage/legacy/hdfs'],
525
- snowflake: DW_LOGO_URIS['storage/legacy/snowflake'],
526
- bigquery: DW_LOGO_URIS['storage/legacy/bigquery'],
527
- databricks: DW_LOGO_URIS['storage/legacy/databricks'],
528
- datastax: DW_LOGO_URIS['storage/legacy/datastax'],
529
- mysql: DW_LOGO_URIS['storage/legacy/mysql'],
530
- postgres: DW_LOGO_URIS['storage/legacy/postgres'],
531
- cockroach: DW_LOGO_URIS['storage/legacy/cockroach'],
532
- oracle: DW_LOGO_URIS['storage/legacy/oracle'],
533
- mariadb: DW_LOGO_URIS['storage/legacy/mariadb'],
534
- db2: DW_LOGO_URIS['storage/legacy/db2'],
535
- sqlserver: DW_LOGO_URIS['storage/legacy/sqlserver'],
536
- mongodb: DW_LOGO_URIS['storage/legacy/mongodb'],
537
- elastic: DW_LOGO_URIS['storage/legacy/elastic'],
538
- aerospike: DW_LOGO_URIS['storage/legacy/aerospike'],
539
- redshift: DW_LOGO_URIS['storage/legacy/redshift'],
540
- kafka: DW_LOGO_URIS['storage/legacy/kafka'],
541
- pinecone: DW_LOGO_URIS['storage/legacy/pinecone'],
542
- neo4j: DW_LOGO_URIS['storage/legacy/neo4j'],
543
- opensearch: DW_LOGO_URIS['storage/legacy/opensearch'],
544
- couchbase: DW_LOGO_URIS['storage/legacy/couchbase'],
545
- salesforce: DW_LOGO_URIS['storage/legacy/salesforce'],
546
- marketo: DW_LOGO_URIS['storage/legacy/marketo'],
547
- hubspot: DW_LOGO_URIS['storage/legacy/hubspot'],
548
- jira: DW_LOGO_URIS['storage/legacy/jira'],
549
- zoom: DW_LOGO_URIS['storage/legacy/zoom'],
550
- outreach: DW_LOGO_URIS['storage/legacy/outreach'],
551
- pendo: DW_LOGO_URIS['storage/legacy/pendo'],
552
- 'google-sheets': DW_LOGO_URIS['storage/legacy/google-sheets'],
553
- storagebridge: DW_LOGO_URIS['storage/legacy/storagebridge'],
554
- onedrive: DW_LOGO_URIS['storage/legacy/onedrive'],
555
- sharepoint: DW_LOGO_URIS['storage/legacy/sharepoint'],
556
- googledrive: DW_LOGO_URIS['storage/legacy/googledrive'],
557
- nas: DW_LOGO_URIS['storage/legacy/nas'],
558
- upload: DW_LOGO_URIS['storage/legacy/upload'],
559
- filestream: DW_LOGO_URIS['storage/legacy/filestream'],
560
- 'broadcom-clarity': DW_LOGO_URIS['storage/legacy/broadcom-clarity'],
561
- // dataworkz-web has no artwork of its own for it: the same file as `local`.
562
- 'microsoft-mail': DW_LOGO_URIS['storage/legacy/microsoft-mail'],
563
- };
564
- /** File-source artwork for the data-collections drawers. */
565
- const SOURCES_ICONS = {
566
- s3: DW_LOGO_URIS['storage/sources/s3'],
567
- azure: DW_LOGO_URIS['storage/sources/azure'],
568
- 'google-cloud': DW_LOGO_URIS['storage/sources/google-cloud'],
569
- sharepoint: DW_LOGO_URIS['storage/sources/sharepoint'],
570
- onedrive: DW_LOGO_URIS['storage/sources/onedrive'],
571
- googledrive: DW_LOGO_URIS['storage/sources/googledrive'],
572
- nas: DW_LOGO_URIS['storage/sources/nas'],
573
- };
574
- const ICON_SETS = {
575
- local: LOCAL_ICONS,
576
- legacy: LEGACY_ICONS,
577
- sources: SOURCES_ICONS,
578
- };
291
+ /** What each set falls back to: the generic icon, or nothing for `sources` (its callers hide the icon slot). */
579
292
  const SET_FALLBACK = {
580
293
  local: GENERIC_STORAGE_ICON,
581
- legacy: GENERIC_STORAGE_ICON_LEGACY,
582
- // The drawers hide the icon slot entirely when a source has no artwork.
294
+ legacy: GENERIC_STORAGE_ICON,
583
295
  sources: '',
584
296
  };
585
- /** Canonical family for a `storageType`, or `null` when unknown. */
586
- function resolveStorageIconKey(storageType) {
587
- const normalized = String(storageType ?? '')
588
- .trim()
589
- .toLowerCase();
590
- if (!normalized)
591
- return null;
592
- return STORAGE_TYPE_TO_KEY[normalized] ?? null;
297
+ /** The storage icon keys a set has artwork for. */
298
+ function storageIconKeys(set = 'local') {
299
+ const prefix = `storage/${set}/`;
300
+ return Object.keys(DW_LOGO_URIS)
301
+ .filter((path) => path.startsWith(prefix))
302
+ .map((path) => path.slice(prefix.length));
593
303
  }
594
304
  /**
595
- * Icon (a data URI) for a storage / SaaS connector type. The only place a storage
596
- * icon is decided. (The name is kept from when it returned an asset path.)
305
+ * The storage icon (a data URI) for a key in a set, e.g. `storageIcon('s3')` or `storageIcon('upload', { set: 'legacy' })`,
306
+ * else the set's fallback. Keys are crystal's artwork names; map your own storage types to them (e.g. with
307
+ * `provideCrystalIconResolvers()`).
597
308
  */
598
- function getStorageIconPath(storageType, options = {}) {
309
+ function storageIcon(key, options = {}) {
599
310
  const set = options.set ?? 'local';
600
- const key = resolveStorageIconKey(storageType);
601
- const icon = key ? ICON_SETS[set][key] : undefined;
602
- return icon ?? options.fallback ?? SET_FALLBACK[set];
311
+ const uri = key ? DW_LOGO_URIS[`storage/${set}/${key}`] : undefined;
312
+ return uri ?? options.fallback ?? SET_FALLBACK[set];
603
313
  }
604
314
 
605
315
  const FILE_EXTENSION_GROUPS = {
@@ -651,7 +361,7 @@ const MIME_BY_EXTENSION = {
651
361
  m4a: 'audio/m4a',
652
362
  flac: 'audio/flac',
653
363
  };
654
- /** File-type icons, inlined as data URIs (icons/svg/files/<key>.svg). */
364
+ /** File-type icons, inlined as data URIs (icons/svg/files/`<key>`.svg). */
655
365
  const FILE_TYPE_ICON_PATHS = {
656
366
  word: DW_LOGO_URIS['files/word'],
657
367
  text: DW_LOGO_URIS['files/text'],
@@ -821,13 +531,13 @@ function sourceTypeLabelByExtension(extension) {
821
531
  }
822
532
 
823
533
  /*
824
- * @dataworkz/crystal/icons — framework-free icon names and lookups (no Angular imports).
825
- * P2 moves the glyphs into .svg files and makes the lookups return data URIs (MIGRATION-PLAN §2.2).
534
+ * @dataworkz/crystal/icons — framework-free icon names, markup and logos (no Angular imports). Every icon is a file in
535
+ * icons/svg/, inlined: glyphs as markup, logos as data URIs.
826
536
  */
827
537
 
828
538
  /**
829
539
  * Generated bundle index. Do not edit.
830
540
  */
831
541
 
832
- export { AGENT_NODE_ICON, BUILT_IN_TOOL_ICON, DW_ICON_NAMES, DW_ICON_PREFIX, DW_LOGO_URIS, GENERIC_COLLECTION_ICON, GENERIC_STORAGE_ICON, GENERIC_STORAGE_ICON_LEGACY, GENERIC_TOOL_ICON, dwIconName, fileIconByExtension, getStorageIconPath, getToolIconPath, icon, isGlyphName, resolveStorageIconKey, resolveToolIconKey };
542
+ export { DW_ICON_NAMES, DW_ICON_PREFIX, DW_LOGO_URIS, GENERIC_COLLECTION_ICON, GENERIC_STORAGE_ICON, GENERIC_TOOL_ICON, TOOL_ICON_KEYS, dwIconName, fileIconByExtension, icon, isGlyphName, isToolIconKey, storageIcon, storageIconKeys, toolIcon };
833
543
  //# sourceMappingURL=dataworkz-crystal-icons.mjs.map