@zeyos/zx 2.1.0 → 2.2.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.
- package/CHANGELOG.md +39 -0
- package/README.md +15 -0
- package/dist/types/compat/base.d.ts +156 -0
- package/dist/types/compat/globals.d.ts +20 -0
- package/dist/types/compat/index.d.ts +128 -0
- package/dist/types/compat/map/basic.d.ts +175 -0
- package/dist/types/compat/map/data.d.ts +102 -0
- package/dist/types/compat/map/date-time.d.ts +80 -0
- package/dist/types/compat/map/factory.d.ts +9 -0
- package/dist/types/compat/map/form.d.ts +98 -0
- package/dist/types/compat/map/helpers.d.ts +12 -0
- package/dist/types/compat/map/http.d.ts +36 -0
- package/dist/types/compat/map/layout.d.ts +106 -0
- package/dist/types/compat/map/options.d.ts +80 -0
- package/dist/types/compat/map/select.d.ts +95 -0
- package/dist/types/compat/map/stubs.d.ts +32 -0
- package/dist/types/compat/map/utilities.d.ts +37 -0
- package/dist/types/compat-entry.d.ts +5 -0
- package/dist/types/components/badge/badge.d.ts +46 -0
- package/dist/types/components/breadcrumb/breadcrumb.d.ts +200 -0
- package/dist/types/components/button/button.d.ts +42 -0
- package/dist/types/components/check-button/check-button.d.ts +98 -0
- package/dist/types/components/checklist/checklist.d.ts +143 -0
- package/dist/types/components/checklist/field-adapter.d.ts +5 -0
- package/dist/types/components/context-menu/context-menu.d.ts +130 -0
- package/dist/types/components/copy/copy-button.d.ts +48 -0
- package/dist/types/components/copy/copy-input.d.ts +91 -0
- package/dist/types/components/data-filter/data-filter.d.ts +250 -0
- package/dist/types/components/data-filter/filter-core.d.ts +52 -0
- package/dist/types/components/date-picker/date-picker.d.ts +137 -0
- package/dist/types/components/date-picker/date-range-picker.d.ts +350 -0
- package/dist/types/components/date-picker/field-adapter.d.ts +6 -0
- package/dist/types/components/date-picker/month-picker.d.ts +75 -0
- package/dist/types/components/date-picker/range-field-adapter.d.ts +7 -0
- package/dist/types/components/date-picker/time-picker.d.ts +127 -0
- package/dist/types/components/datebox/date-range-box.d.ts +218 -0
- package/dist/types/components/datebox/datebox.d.ts +160 -0
- package/dist/types/components/datebox/field-adapter.d.ts +5 -0
- package/dist/types/components/dialog/dialog.d.ts +284 -0
- package/dist/types/components/dropdown/dropdown.d.ts +118 -0
- package/dist/types/components/empty-state/empty-state.d.ts +38 -0
- package/dist/types/components/field/field.d.ts +231 -0
- package/dist/types/components/field-upload/field-adapter.d.ts +5 -0
- package/dist/types/components/field-upload/field-upload.d.ts +213 -0
- package/dist/types/components/fieldset/fieldset.d.ts +125 -0
- package/dist/types/components/finder/finder.d.ts +252 -0
- package/dist/types/components/form/form.d.ts +194 -0
- package/dist/types/components/groupbox/groupbox.d.ts +89 -0
- package/dist/types/components/layout/layout.d.ts +132 -0
- package/dist/types/components/loading/inline-loading.d.ts +86 -0
- package/dist/types/components/loading/progress-bar.d.ts +168 -0
- package/dist/types/components/loading/spinner.d.ts +34 -0
- package/dist/types/components/master-panel/master-panel.d.ts +112 -0
- package/dist/types/components/menu-button/menu-button.d.ts +142 -0
- package/dist/types/components/message/message.d.ts +212 -0
- package/dist/types/components/modal/modal.d.ts +105 -0
- package/dist/types/components/multi-value-editor/field-adapter.d.ts +5 -0
- package/dist/types/components/multi-value-editor/multi-value-editor.d.ts +66 -0
- package/dist/types/components/navigation-bar/navigation-bar.d.ts +229 -0
- package/dist/types/components/number-field/field-adapter.d.ts +5 -0
- package/dist/types/components/number-field/number-field.d.ts +292 -0
- package/dist/types/components/pagination/pagination.d.ts +267 -0
- package/dist/types/components/panel/panel.d.ts +194 -0
- package/dist/types/components/permission/permission.d.ts +93 -0
- package/dist/types/components/rating/field-adapter.d.ts +5 -0
- package/dist/types/components/rating/rating.d.ts +213 -0
- package/dist/types/components/search/search.d.ts +98 -0
- package/dist/types/components/select/field-adapter.d.ts +5 -0
- package/dist/types/components/select/filter.d.ts +11 -0
- package/dist/types/components/select/select.d.ts +235 -0
- package/dist/types/components/skeleton/skeleton.d.ts +97 -0
- package/dist/types/components/slider/field-adapter.d.ts +5 -0
- package/dist/types/components/slider/slider.d.ts +216 -0
- package/dist/types/components/split-view/split-view.d.ts +335 -0
- package/dist/types/components/stepper/stepper.d.ts +314 -0
- package/dist/types/components/stepper/steps.d.ts +131 -0
- package/dist/types/components/tabbox/tabbox.d.ts +230 -0
- package/dist/types/components/table/sort.d.ts +49 -0
- package/dist/types/components/table/table.d.ts +872 -0
- package/dist/types/components/tag-picker/field-adapter.d.ts +5 -0
- package/dist/types/components/tag-picker/tag-picker.d.ts +375 -0
- package/dist/types/components/timebox/field-adapter.d.ts +5 -0
- package/dist/types/components/timebox/timebox.d.ts +121 -0
- package/dist/types/components/toggle/field-adapter.d.ts +5 -0
- package/dist/types/components/toggle/toggle.d.ts +94 -0
- package/dist/types/components/toolbar/toolbar.d.ts +230 -0
- package/dist/types/components/tooltip/tooltip.d.ts +183 -0
- package/dist/types/components/tree/hierarchy.d.ts +113 -0
- package/dist/types/components/tree/tree.d.ts +383 -0
- package/dist/types/components/truncate/truncate.d.ts +61 -0
- package/dist/types/components/value-list/field-adapter.d.ts +5 -0
- package/dist/types/components/value-list/value-list.d.ts +143 -0
- package/dist/types/core/breakpoint.d.ts +68 -0
- package/dist/types/core/component.d.ts +115 -0
- package/dist/types/core/date.d.ts +50 -0
- package/dist/types/core/dom.d.ts +86 -0
- package/dist/types/core/export.d.ts +70 -0
- package/dist/types/core/fontawesome.d.ts +107 -0
- package/dist/types/core/format.d.ts +107 -0
- package/dist/types/core/http.d.ts +122 -0
- package/dist/types/core/i18n.d.ts +35 -0
- package/dist/types/core/icons.d.ts +137 -0
- package/dist/types/core/keyboard.d.ts +72 -0
- package/dist/types/core/position.d.ts +45 -0
- package/dist/types/core/storage.d.ts +46 -0
- package/dist/types/core/util.d.ts +117 -0
- package/dist/types/elements/define.d.ts +73 -0
- package/dist/types/elements/reflect.d.ts +27 -0
- package/dist/types/index.d.ts +79 -0
- package/dist/types/zeyos/connect.d.ts +65 -0
- package/dist/types/zeyos/form.d.ts +140 -0
- package/dist/types/zeyos/icons.d.ts +104 -0
- package/dist/types/zeyos/index.d.ts +12 -0
- package/dist/types/zeyos/modules.d.ts +110 -0
- package/dist/types/zeyos/query.d.ts +157 -0
- package/dist/types/zeyos/schema.d.ts +79 -0
- package/dist/types/zeyos/select.d.ts +167 -0
- package/dist/types/zeyos/table.d.ts +205 -0
- package/dist/zx-compat.esm.js +362 -33
- package/dist/zx-compat.esm.min.js +1 -1
- package/dist/zx-compat.global.js +359 -67
- package/dist/zx-compat.global.min.js +3 -3
- package/dist/zx-zeyos.esm.js +342 -43
- package/dist/zx-zeyos.esm.min.js +1 -1
- package/dist/zx.css +68 -6
- package/dist/zx.esm.js +346 -67
- package/dist/zx.esm.min.js +3 -3
- package/dist/zx.global.js +346 -67
- package/dist/zx.global.min.js +3 -3
- package/dist/zx.min.css +1 -1
- package/docs/api.json +48 -2
- package/docs/llms.md +28 -0
- package/package.json +37 -9
- package/src/compat/base.js +291 -0
- package/src/compat/globals.js +165 -0
- package/src/compat/index.js +84 -0
- package/src/compat/map/basic.js +464 -0
- package/src/compat/map/data.js +232 -0
- package/src/compat/map/date-time.js +177 -0
- package/src/compat/map/factory.js +45 -0
- package/src/compat/map/form.js +330 -0
- package/src/compat/map/helpers.js +46 -0
- package/src/compat/map/http.js +117 -0
- package/src/compat/map/layout.js +256 -0
- package/src/compat/map/options.js +267 -0
- package/src/compat/map/select.js +198 -0
- package/src/compat/map/stubs.js +26 -0
- package/src/compat/map/utilities.js +113 -0
- package/src/compat-entry.js +11 -0
- package/src/components/badge/badge.css +147 -0
- package/src/components/badge/badge.js +92 -0
- package/src/components/breadcrumb/breadcrumb.css +105 -0
- package/src/components/breadcrumb/breadcrumb.js +331 -0
- package/src/components/button/button.css +104 -0
- package/src/components/button/button.js +76 -0
- package/src/components/check-button/check-button.css +66 -0
- package/src/components/check-button/check-button.js +167 -0
- package/src/components/checklist/checklist.css +65 -0
- package/src/components/checklist/checklist.js +282 -0
- package/src/components/checklist/field-adapter.js +46 -0
- package/src/components/context-menu/context-menu.css +54 -0
- package/src/components/context-menu/context-menu.js +334 -0
- package/src/components/copy/copy-button.css +27 -0
- package/src/components/copy/copy-button.js +78 -0
- package/src/components/copy/copy-input.css +59 -0
- package/src/components/copy/copy-input.js +123 -0
- package/src/components/data-filter/data-filter.css +53 -0
- package/src/components/data-filter/data-filter.js +400 -0
- package/src/components/data-filter/filter-core.js +128 -0
- package/src/components/date-picker/date-picker.css +181 -0
- package/src/components/date-picker/date-picker.js +500 -0
- package/src/components/date-picker/date-range-picker.css +264 -0
- package/src/components/date-picker/date-range-picker.js +990 -0
- package/src/components/date-picker/field-adapter.js +36 -0
- package/src/components/date-picker/month-picker.js +223 -0
- package/src/components/date-picker/range-field-adapter.js +31 -0
- package/src/components/date-picker/time-picker.css +191 -0
- package/src/components/date-picker/time-picker.js +406 -0
- package/src/components/datebox/date-range-box.css +128 -0
- package/src/components/datebox/date-range-box.js +492 -0
- package/src/components/datebox/datebox.css +108 -0
- package/src/components/datebox/datebox.js +358 -0
- package/src/components/datebox/field-adapter.js +34 -0
- package/src/components/dialog/dialog.css +74 -0
- package/src/components/dialog/dialog.js +450 -0
- package/src/components/dropdown/dropdown.css +24 -0
- package/src/components/dropdown/dropdown.js +288 -0
- package/src/components/empty-state/empty-state.css +80 -0
- package/src/components/empty-state/empty-state.js +92 -0
- package/src/components/field/field.css +127 -0
- package/src/components/field/field.js +605 -0
- package/src/components/field-upload/field-adapter.js +21 -0
- package/src/components/field-upload/field-upload.css +108 -0
- package/src/components/field-upload/field-upload.js +475 -0
- package/src/components/fieldset/fieldset.css +37 -0
- package/src/components/fieldset/fieldset.js +307 -0
- package/src/components/finder/finder.css +98 -0
- package/src/components/finder/finder.js +509 -0
- package/src/components/form/form.css +32 -0
- package/src/components/form/form.js +302 -0
- package/src/components/groupbox/groupbox.css +51 -0
- package/src/components/groupbox/groupbox.js +199 -0
- package/src/components/layout/layout.css +117 -0
- package/src/components/layout/layout.js +136 -0
- package/src/components/loading/inline-loading.css +34 -0
- package/src/components/loading/inline-loading.js +140 -0
- package/src/components/loading/progress-bar.css +115 -0
- package/src/components/loading/progress-bar.js +259 -0
- package/src/components/loading/spinner.css +58 -0
- package/src/components/loading/spinner.js +57 -0
- package/src/components/master-panel/master-panel.css +51 -0
- package/src/components/master-panel/master-panel.js +203 -0
- package/src/components/menu-button/menu-button.css +49 -0
- package/src/components/menu-button/menu-button.js +294 -0
- package/src/components/message/message.css +122 -0
- package/src/components/message/message.js +499 -0
- package/src/components/modal/modal.css +47 -0
- package/src/components/modal/modal.js +203 -0
- package/src/components/multi-value-editor/field-adapter.js +44 -0
- package/src/components/multi-value-editor/multi-value-editor.css +56 -0
- package/src/components/multi-value-editor/multi-value-editor.js +170 -0
- package/src/components/navigation-bar/navigation-bar.css +130 -0
- package/src/components/navigation-bar/navigation-bar.js +450 -0
- package/src/components/number-field/field-adapter.js +40 -0
- package/src/components/number-field/number-field.css +77 -0
- package/src/components/number-field/number-field.js +545 -0
- package/src/components/pagination/pagination.css +95 -0
- package/src/components/pagination/pagination.js +481 -0
- package/src/components/panel/panel.css +123 -0
- package/src/components/panel/panel.js +336 -0
- package/src/components/permission/permission.css +47 -0
- package/src/components/permission/permission.js +198 -0
- package/src/components/rating/field-adapter.js +34 -0
- package/src/components/rating/rating.css +97 -0
- package/src/components/rating/rating.js +395 -0
- package/src/components/search/search.css +70 -0
- package/src/components/search/search.js +193 -0
- package/src/components/select/field-adapter.js +24 -0
- package/src/components/select/filter.js +39 -0
- package/src/components/select/select.css +180 -0
- package/src/components/select/select.js +663 -0
- package/src/components/skeleton/skeleton.css +76 -0
- package/src/components/skeleton/skeleton.js +139 -0
- package/src/components/slider/field-adapter.js +36 -0
- package/src/components/slider/slider.css +181 -0
- package/src/components/slider/slider.js +399 -0
- package/src/components/split-view/split-view.css +139 -0
- package/src/components/split-view/split-view.js +806 -0
- package/src/components/stepper/stepper.css +234 -0
- package/src/components/stepper/stepper.js +459 -0
- package/src/components/stepper/steps.js +131 -0
- package/src/components/tabbox/tabbox.css +281 -0
- package/src/components/tabbox/tabbox.js +484 -0
- package/src/components/table/sort.js +85 -0
- package/src/components/table/table.css +364 -0
- package/src/components/table/table.js +1693 -0
- package/src/components/tag-picker/field-adapter.js +35 -0
- package/src/components/tag-picker/tag-picker.css +169 -0
- package/src/components/tag-picker/tag-picker.js +837 -0
- package/src/components/timebox/field-adapter.js +24 -0
- package/src/components/timebox/timebox.css +51 -0
- package/src/components/timebox/timebox.js +276 -0
- package/src/components/toggle/field-adapter.js +24 -0
- package/src/components/toggle/toggle.css +66 -0
- package/src/components/toggle/toggle.js +150 -0
- package/src/components/toolbar/toolbar.css +81 -0
- package/src/components/toolbar/toolbar.js +511 -0
- package/src/components/tooltip/tooltip.css +36 -0
- package/src/components/tooltip/tooltip.js +420 -0
- package/src/components/tree/hierarchy.js +151 -0
- package/src/components/tree/tree.css +99 -0
- package/src/components/tree/tree.js +784 -0
- package/src/components/truncate/truncate.css +20 -0
- package/src/components/truncate/truncate.js +92 -0
- package/src/components/value-list/field-adapter.js +24 -0
- package/src/components/value-list/value-list.css +108 -0
- package/src/components/value-list/value-list.js +336 -0
- package/src/core/breakpoint.js +150 -0
- package/src/core/component.js +292 -0
- package/src/core/date.js +216 -0
- package/src/core/dom.js +260 -0
- package/src/core/export.js +204 -0
- package/src/core/fontawesome.js +177 -0
- package/src/core/format.js +283 -0
- package/src/core/http.js +246 -0
- package/src/core/i18n.js +83 -0
- package/src/core/icons.js +283 -0
- package/src/core/keyboard.js +240 -0
- package/src/core/position.js +177 -0
- package/src/core/storage.js +175 -0
- package/src/core/util.js +336 -0
- package/src/elements/define.js +715 -0
- package/src/elements/reflect.js +79 -0
- package/src/index.js +131 -0
- package/src/zeyos/connect.js +142 -0
- package/src/zeyos/form.js +254 -0
- package/src/zeyos/icons.js +92 -0
- package/src/zeyos/index.js +21 -0
- package/src/zeyos/modules.js +269 -0
- package/src/zeyos/query.js +199 -0
- package/src/zeyos/schema.js +474 -0
- package/src/zeyos/select.js +175 -0
- package/src/zeyos/table.js +272 -0
- package/styles/base.css +124 -0
- package/styles/icons.css +34 -0
- package/styles/tokens/dark.css +84 -0
- package/styles/tokens/density.css +9 -0
- package/styles/tokens/global.css +80 -0
- package/styles/tokens/modules.css +109 -0
- package/styles/tokens/semantic.css +49 -0
- package/styles/zx.css +61 -0
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
import { Table } from '../index.js';
|
|
2
|
+
import { connect } from './connect.js';
|
|
3
|
+
import { buildListQuery } from './query.js';
|
|
4
|
+
import { fieldToZxColumn, resolveFields } from './schema.js';
|
|
5
|
+
import { normalizeZeyosListResult } from './select.js';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @typedef {Object} ZeyosTableOptions
|
|
9
|
+
* @property {string[]} [fields] Curated ordered field allow-list.
|
|
10
|
+
* @property {Record<string, string>} [labels] Per-field label overrides.
|
|
11
|
+
* @property {string|((row: Record<string, unknown>) => unknown)} [rowId='ID'] Row id accessor.
|
|
12
|
+
* @property {number} [pageSize=50] Server page size.
|
|
13
|
+
* @property {{id: string, dir: 'asc'|'desc'}|null} [sort=null] Initial server sort.
|
|
14
|
+
* @property {Record<string, unknown>} [filters] Initial ZeyOS predicates.
|
|
15
|
+
* @property {string} [search=''] Initial full-text query.
|
|
16
|
+
* @property {false|'single'|'multi'} [selectable=false] Row selection mode.
|
|
17
|
+
* @property {number|string|null} [height=null] Table scroll-region height.
|
|
18
|
+
* @property {(row: Record<string, unknown>, event: CustomEvent<Record<string, unknown>>) => void} [onRowClick] Row activation callback.
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* @typedef {Object} ZeyosTableConfig
|
|
23
|
+
* @property {Record<string, any>[]} fieldMeta Ordered normalized schema metadata.
|
|
24
|
+
* @property {Record<string, any>[]} columns Generated Zx columns.
|
|
25
|
+
* @property {Record<string, string>} projection API projection including row ids/entity labels.
|
|
26
|
+
* @property {Record<string, any>} tableOptions Plain Zx Table options.
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* @typedef {Object} ZeyosTableLoadOptions
|
|
31
|
+
* @property {string} [search] Replacement full-text query.
|
|
32
|
+
* @property {Record<string, unknown>} [filters] Replacement ZeyOS predicates.
|
|
33
|
+
* @property {number} [page=0] Zero-based page; pages above zero append rows.
|
|
34
|
+
*/
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* @typedef {Object} ZeyosTableLoadResult
|
|
38
|
+
* @property {Record<string, unknown>[]} data Loaded page rows.
|
|
39
|
+
* @property {number|null} count Server count when supplied.
|
|
40
|
+
* @property {number} page Loaded zero-based page.
|
|
41
|
+
* @property {boolean} hasMore Whether another page is available.
|
|
42
|
+
* @property {Record<string, unknown>} query Request passed to the list operation.
|
|
43
|
+
*/
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* @typedef {Object} ZeyosTableBinding
|
|
47
|
+
* @property {Table} table Generated Zx table.
|
|
48
|
+
* @property {(options?: ZeyosTableLoadOptions) => Promise<ZeyosTableLoadResult>} load Loads/reloads a server page.
|
|
49
|
+
* @property {(search: string) => Promise<ZeyosTableLoadResult>} setSearch Replaces search and reloads page zero.
|
|
50
|
+
* @property {(filters: Record<string, unknown>) => Promise<ZeyosTableLoadResult>} setFilters Replaces predicates and reloads page zero.
|
|
51
|
+
* @property {() => Promise<ZeyosTableLoadResult>} loadMore Appends the next page when available.
|
|
52
|
+
* @property {number|null} count Current server count.
|
|
53
|
+
* @property {number} page Current zero-based page.
|
|
54
|
+
* @property {boolean} hasMore Whether another page is available.
|
|
55
|
+
* @property {() => void} destroy Destroys the generated table.
|
|
56
|
+
*/
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Builds the DOM-free schema-derived columns and Table options used by {@link zeyosTable}. Entity
|
|
60
|
+
* projections include an `<field>_label` alias from a real label field on the referenced resource.
|
|
61
|
+
* Amount fields use each row's real `currency` value for display while retaining the WP14 typed
|
|
62
|
+
* column strategy and right alignment.
|
|
63
|
+
* @param {Record<string, any>} client Injected ZeyOS client instance.
|
|
64
|
+
* @param {string} resource Resource name such as `transactions`.
|
|
65
|
+
* @param {ZeyosTableOptions} [opts={}] Schema, table, and initial query options.
|
|
66
|
+
* @returns {ZeyosTableConfig} Plain columns, projection, and Table options.
|
|
67
|
+
*/
|
|
68
|
+
export function buildZeyosTableConfig(client, resource, opts = {}) {
|
|
69
|
+
const fieldMeta = resolveFields(client, resource, {
|
|
70
|
+
fields: opts.fields,
|
|
71
|
+
labels: opts.labels
|
|
72
|
+
});
|
|
73
|
+
const projection = {};
|
|
74
|
+
const columns = fieldMeta.map((sourceMeta) => {
|
|
75
|
+
const meta = { ...sourceMeta };
|
|
76
|
+
const referencedResource = referencedResourceFor(meta);
|
|
77
|
+
if (referencedResource) {
|
|
78
|
+
const labelKey = inferLabelKey(client, referencedResource);
|
|
79
|
+
meta.labelField = `${meta.id}_label`;
|
|
80
|
+
projection[meta.labelField] = `${meta.id}.${labelKey}`;
|
|
81
|
+
}
|
|
82
|
+
projection[meta.id] = meta.id;
|
|
83
|
+
|
|
84
|
+
const monetary = isMonetaryField(meta);
|
|
85
|
+
const column = fieldToZxColumn(monetary ? { ...meta, format: 'money' } : meta);
|
|
86
|
+
if (monetary) {
|
|
87
|
+
column.render = (row) => formatCurrency(row?.[meta.id], row?.currency);
|
|
88
|
+
if (schemaHasField(client, resource, 'currency')) projection.currency = 'currency';
|
|
89
|
+
}
|
|
90
|
+
return column;
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
const rowId = opts.rowId ?? 'ID';
|
|
94
|
+
if (typeof rowId === 'string' && !Object.prototype.hasOwnProperty.call(projection, rowId)) {
|
|
95
|
+
projection[rowId] = rowId;
|
|
96
|
+
}
|
|
97
|
+
return {
|
|
98
|
+
fieldMeta,
|
|
99
|
+
columns,
|
|
100
|
+
projection,
|
|
101
|
+
tableOptions: {
|
|
102
|
+
columns,
|
|
103
|
+
data: [],
|
|
104
|
+
rowId,
|
|
105
|
+
sort: opts.sort ?? null,
|
|
106
|
+
sortMode: 'server',
|
|
107
|
+
selectable: opts.selectable ?? false,
|
|
108
|
+
height: opts.height ?? null,
|
|
109
|
+
onrowclick: typeof opts.onRowClick === 'function'
|
|
110
|
+
? (event) => opts.onRowClick(event.detail.row, event)
|
|
111
|
+
: undefined
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Generates a server-backed Zx Table. Sorting automatically reloads page zero. `load({page: 0})`
|
|
118
|
+
* replaces data, higher pages append it, and `loadMore()` uses `limit`/`offset` plus the returned
|
|
119
|
+
* count. DataFilter callers can map state with `dataFilterStateToFilters` before `setFilters()`.
|
|
120
|
+
* @param {Record<string, any>} client Injected ZeyOS client instance.
|
|
121
|
+
* @param {string} resource Resource name such as `transactions`.
|
|
122
|
+
* @param {ZeyosTableOptions} [opts={}] Schema, table, and initial query options.
|
|
123
|
+
* @returns {ZeyosTableBinding} Generated table and server-state methods/getters.
|
|
124
|
+
*/
|
|
125
|
+
export function zeyosTable(client, resource, opts = {}) {
|
|
126
|
+
const config = buildZeyosTableConfig(client, resource, opts);
|
|
127
|
+
const facade = connect(client);
|
|
128
|
+
const table = new Table(null, config.tableOptions);
|
|
129
|
+
const pageSize = normalizePageSize(opts.pageSize);
|
|
130
|
+
let currentSort = opts.sort ?? null;
|
|
131
|
+
let currentFilters = copyFilters(opts.filters ?? {});
|
|
132
|
+
let currentSearch = String(opts.search ?? '');
|
|
133
|
+
let currentPage = 0;
|
|
134
|
+
let totalCount = null;
|
|
135
|
+
let more = false;
|
|
136
|
+
let requestSequence = 0;
|
|
137
|
+
|
|
138
|
+
const load = async (options = {}) => {
|
|
139
|
+
if (Object.prototype.hasOwnProperty.call(options, 'search')) currentSearch = String(options.search ?? '');
|
|
140
|
+
if (Object.prototype.hasOwnProperty.call(options, 'filters')) currentFilters = copyFilters(options.filters ?? {});
|
|
141
|
+
const page = normalizePage(options.page ?? 0);
|
|
142
|
+
const query = buildListQuery({
|
|
143
|
+
fields: config.projection,
|
|
144
|
+
sort: currentSort,
|
|
145
|
+
filters: currentFilters,
|
|
146
|
+
search: currentSearch,
|
|
147
|
+
limit: pageSize,
|
|
148
|
+
offset: page * pageSize,
|
|
149
|
+
count: true
|
|
150
|
+
});
|
|
151
|
+
const sequence = ++requestSequence;
|
|
152
|
+
table.setLoading(true);
|
|
153
|
+
try {
|
|
154
|
+
const normalized = normalizeZeyosListResult(client, await facade.list(resource, query));
|
|
155
|
+
const count = normalized.count ?? null;
|
|
156
|
+
const hasMore = count == null
|
|
157
|
+
? normalized.data.length === pageSize
|
|
158
|
+
: (page * pageSize + normalized.data.length) < count;
|
|
159
|
+
if (sequence === requestSequence) {
|
|
160
|
+
currentPage = page;
|
|
161
|
+
totalCount = count;
|
|
162
|
+
more = hasMore;
|
|
163
|
+
if (page === 0) table.setData(normalized.data);
|
|
164
|
+
else table.addData(normalized.data);
|
|
165
|
+
}
|
|
166
|
+
return { data: normalized.data, count, page, hasMore, query };
|
|
167
|
+
} finally {
|
|
168
|
+
if (sequence === requestSequence) table.setLoading(false);
|
|
169
|
+
}
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
const binding = {
|
|
173
|
+
table,
|
|
174
|
+
load,
|
|
175
|
+
setSearch: (search) => load({ search, page: 0 }),
|
|
176
|
+
setFilters: (filters) => load({ filters, page: 0 }),
|
|
177
|
+
loadMore: () => more ? load({ page: currentPage + 1 }) : Promise.resolve({
|
|
178
|
+
data: [],
|
|
179
|
+
count: totalCount,
|
|
180
|
+
page: currentPage,
|
|
181
|
+
hasMore: false,
|
|
182
|
+
query: buildListQuery({
|
|
183
|
+
fields: config.projection,
|
|
184
|
+
sort: currentSort,
|
|
185
|
+
filters: currentFilters,
|
|
186
|
+
search: currentSearch,
|
|
187
|
+
limit: pageSize,
|
|
188
|
+
offset: currentPage * pageSize,
|
|
189
|
+
count: true
|
|
190
|
+
})
|
|
191
|
+
}),
|
|
192
|
+
get count() { return totalCount; },
|
|
193
|
+
get page() { return currentPage; },
|
|
194
|
+
get hasMore() { return more; },
|
|
195
|
+
destroy: () => table.destroy()
|
|
196
|
+
};
|
|
197
|
+
|
|
198
|
+
table.on('sort', (event) => {
|
|
199
|
+
currentSort = { id: String(event.detail.id), dir: event.detail.dir === 'desc' ? 'desc' : 'asc' };
|
|
200
|
+
void load({ page: 0 }).catch(() => { /* The connection facade already reported the failure. */ });
|
|
201
|
+
});
|
|
202
|
+
return binding;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/** @param {Record<string, any>} meta @returns {string|null} */
|
|
206
|
+
function referencedResourceFor(meta) {
|
|
207
|
+
for (const value of [meta.entity, meta.fk, meta.relation, meta.reference, meta.references]) {
|
|
208
|
+
if (typeof value === 'string' && value) return value;
|
|
209
|
+
if (value && typeof value === 'object') {
|
|
210
|
+
const resource = value.resource ?? value.target ?? value.table ?? value.entity;
|
|
211
|
+
if (typeof resource === 'string' && resource) return resource;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
return null;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/** @param {Record<string, any>} client @param {string} resource @returns {string} */
|
|
218
|
+
function inferLabelKey(client, resource) {
|
|
219
|
+
const fields = client?.schema?.fields?.(resource);
|
|
220
|
+
const names = Array.isArray(fields) ? fields.map(String) : Object.keys(fields ?? {});
|
|
221
|
+
for (const candidate of ['name', 'lastname', 'customernum', 'transactionnum', 'number', 'title', 'ID']) {
|
|
222
|
+
if (names.includes(candidate)) return candidate;
|
|
223
|
+
}
|
|
224
|
+
return names[0] ?? 'ID';
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/** @param {Record<string, any>} meta @returns {boolean} */
|
|
228
|
+
function isMonetaryField(meta) {
|
|
229
|
+
const format = String(meta.format ?? '').toLowerCase();
|
|
230
|
+
return /money|currency|price/.test(format) || /(?:amount|price)$/.test(String(meta.id).toLowerCase());
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/** @param {unknown} value @param {unknown} currency @returns {string} */
|
|
234
|
+
function formatCurrency(value, currency) {
|
|
235
|
+
if (value == null || value === '') return '';
|
|
236
|
+
const number = Number(value);
|
|
237
|
+
if (!Number.isFinite(number)) return '';
|
|
238
|
+
const code = typeof currency === 'string' && /^[A-Z]{3}$/.test(currency) ? currency : null;
|
|
239
|
+
try {
|
|
240
|
+
return new Intl.NumberFormat(undefined, code ? { style: 'currency', currency: code } : {}).format(number);
|
|
241
|
+
} catch {
|
|
242
|
+
return new Intl.NumberFormat().format(number);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
/** @param {Record<string, any>} client @param {string} resource @param {string} id @returns {boolean} */
|
|
247
|
+
function schemaHasField(client, resource, id) {
|
|
248
|
+
const fields = client?.schema?.fields?.(resource);
|
|
249
|
+
if (Array.isArray(fields)) return fields.includes(id);
|
|
250
|
+
return Boolean(fields && typeof fields === 'object' && Object.prototype.hasOwnProperty.call(fields, id));
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/** @param {unknown} value @returns {number} */
|
|
254
|
+
function normalizePageSize(value) {
|
|
255
|
+
const number = Number(value ?? 50);
|
|
256
|
+
return Number.isInteger(number) && number > 0 ? number : 50;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/** @param {unknown} value @returns {number} */
|
|
260
|
+
function normalizePage(value) {
|
|
261
|
+
const number = Number(value);
|
|
262
|
+
if (!Number.isInteger(number) || number < 0) throw new RangeError('ZeyOS table page must be a non-negative integer');
|
|
263
|
+
return number;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/** @param {Record<string, unknown>} filters @returns {Record<string, unknown>} */
|
|
267
|
+
function copyFilters(filters) {
|
|
268
|
+
if (!filters || typeof filters !== 'object' || Array.isArray(filters)) {
|
|
269
|
+
throw new TypeError('ZeyOS table filters must be an object');
|
|
270
|
+
}
|
|
271
|
+
return { ...filters };
|
|
272
|
+
}
|
package/styles/base.css
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
.zx-scope,
|
|
2
|
+
.zx-scope *,
|
|
3
|
+
.zx-scope *::before,
|
|
4
|
+
.zx-scope *::after {
|
|
5
|
+
box-sizing: border-box;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
.zx-scope {
|
|
9
|
+
min-block-size: 100%;
|
|
10
|
+
margin: 0;
|
|
11
|
+
background: var(--zx-color-bg-page);
|
|
12
|
+
color: var(--zx-color-text);
|
|
13
|
+
font-family: var(--zx-font-sans);
|
|
14
|
+
font-size: var(--zx-text-md);
|
|
15
|
+
line-height: 1.5;
|
|
16
|
+
-webkit-font-smoothing: antialiased;
|
|
17
|
+
scrollbar-gutter: stable;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/* One focus ring only — ours. Without this the browser keeps painting its own ring (a blue
|
|
21
|
+
outline in Chrome/Safari) at the border edge, so a focused control showed a blue border inside
|
|
22
|
+
our accent glow. The replacement outline is transparent rather than removed: forced-colors mode
|
|
23
|
+
drops box-shadows but forces outline-color to a system colour, so focus stays visible there. */
|
|
24
|
+
.zx-scope :focus-visible {
|
|
25
|
+
outline: 2px solid transparent;
|
|
26
|
+
outline-offset: 2px;
|
|
27
|
+
box-shadow: var(--zx-focus-ring);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.zx-scope ::selection {
|
|
31
|
+
background: var(--zx-color-accent);
|
|
32
|
+
color: var(--zx-color-on-accent);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/* Native-control defaults are wrapped in :where() so they contribute ZERO specificity:
|
|
36
|
+
any component class (.zx-tabbox__tab, .zx-message__close, …) overrides them without a
|
|
37
|
+
specificity fight. This is the default chrome for otherwise-unstyled controls. */
|
|
38
|
+
:where(.zx-scope button:not(.zx-icon-btn)),
|
|
39
|
+
:where(.zx-scope input, .zx-scope select, .zx-scope textarea) {
|
|
40
|
+
min-block-size: var(--zx-control-height);
|
|
41
|
+
border: 1px solid var(--zx-color-border-control);
|
|
42
|
+
border-radius: var(--zx-control-radius);
|
|
43
|
+
background: var(--zx-color-bg-control);
|
|
44
|
+
color: var(--zx-color-text);
|
|
45
|
+
font: inherit;
|
|
46
|
+
font-size: var(--zx-control-font-size);
|
|
47
|
+
transition: color var(--zx-dur-fast) var(--zx-ease),
|
|
48
|
+
background-color var(--zx-dur-fast) var(--zx-ease),
|
|
49
|
+
border-color var(--zx-dur-fast) var(--zx-ease),
|
|
50
|
+
box-shadow var(--zx-dur-fast) var(--zx-ease);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
:where(.zx-scope button:not(.zx-icon-btn)) {
|
|
54
|
+
font-weight: var(--zx-control-font-weight);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
:where(.zx-scope button:not(.zx-icon-btn), .zx-scope select, .zx-scope textarea),
|
|
58
|
+
:where(.zx-scope input:not([type="checkbox"]):not([type="radio"])) {
|
|
59
|
+
padding-inline: var(--zx-control-pad-x);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
:where(.zx-scope button) {
|
|
63
|
+
cursor: pointer;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
:where(.zx-scope button:not(.zx-icon-btn)):hover {
|
|
67
|
+
background: var(--zx-color-bg-hover);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/* Ghost icon button: a borderless, transparent hit target for small glyph actions
|
|
71
|
+
(notification close, closable tab ×, field clear). Square, no chrome until hovered. */
|
|
72
|
+
.zx-scope .zx-icon-btn {
|
|
73
|
+
display: inline-grid;
|
|
74
|
+
place-items: center;
|
|
75
|
+
flex: 0 0 auto;
|
|
76
|
+
inline-size: var(--zx-control-height);
|
|
77
|
+
block-size: var(--zx-control-height);
|
|
78
|
+
padding: 0;
|
|
79
|
+
border: 0;
|
|
80
|
+
border-radius: var(--zx-radius-sm);
|
|
81
|
+
background: none;
|
|
82
|
+
color: var(--zx-color-text-muted);
|
|
83
|
+
cursor: pointer;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
.zx-scope .zx-icon-btn:hover {
|
|
87
|
+
background: var(--zx-color-bg-hover);
|
|
88
|
+
color: var(--zx-color-text);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
.zx-scope .zx-icon-btn:focus-visible {
|
|
92
|
+
outline: 0;
|
|
93
|
+
box-shadow: inset var(--zx-focus-ring);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
.zx-scope .zx-icon-btn:disabled {
|
|
97
|
+
color: var(--zx-color-text-placeholder);
|
|
98
|
+
cursor: not-allowed;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/* Search-term highlight produced by highlightMatch(). No padding and no border, so marking a run
|
|
102
|
+
of text never shifts the line it sits in. */
|
|
103
|
+
.zx-scope .zx-mark {
|
|
104
|
+
padding: 0;
|
|
105
|
+
border-radius: var(--zx-radius-sm);
|
|
106
|
+
background: var(--zx-color-accent-subtle);
|
|
107
|
+
color: var(--zx-color-text);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
.zx-scope input::placeholder,
|
|
111
|
+
.zx-scope textarea::placeholder {
|
|
112
|
+
color: var(--zx-color-text-placeholder);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
@media (prefers-reduced-motion: reduce) {
|
|
116
|
+
.zx-scope *,
|
|
117
|
+
.zx-scope *::before,
|
|
118
|
+
.zx-scope *::after {
|
|
119
|
+
scroll-behavior: auto !important;
|
|
120
|
+
animation-duration: 0.01ms !important;
|
|
121
|
+
animation-iteration-count: 1 !important;
|
|
122
|
+
transition-duration: 0.01ms !important;
|
|
123
|
+
}
|
|
124
|
+
}
|
package/styles/icons.css
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/* Icons.
|
|
2
|
+
Every icon `icon()` builds carries `.zx-icon`, whether it is one of the bundled inline SVG
|
|
3
|
+
glyphs or a Font Awesome element, so the rules below (and component rules) style both. Font
|
|
4
|
+
Awesome icons are sized by font-size and occupy exactly one em. */
|
|
5
|
+
|
|
6
|
+
.zx-icon {
|
|
7
|
+
flex: none;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
i.zx-icon {
|
|
11
|
+
display: inline-block;
|
|
12
|
+
inline-size: 1em;
|
|
13
|
+
block-size: 1em;
|
|
14
|
+
line-height: 1;
|
|
15
|
+
text-align: center;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
svg.zx-icon {
|
|
19
|
+
vertical-align: middle;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/* ZeyOS module icon chip: the module glyph on its identity colour. `moduleChip()` sets the three
|
|
23
|
+
custom properties per module; the glyph is whichever ZeyOS foreground contrasts better. */
|
|
24
|
+
.zx-module-icon {
|
|
25
|
+
display: inline-grid;
|
|
26
|
+
place-items: center;
|
|
27
|
+
flex: none;
|
|
28
|
+
inline-size: var(--zx-module-icon-size, 1.5rem);
|
|
29
|
+
block-size: var(--zx-module-icon-size, 1.5rem);
|
|
30
|
+
border-radius: var(--zx-radius-sm);
|
|
31
|
+
background: var(--zx-module-color, var(--zx-module-default));
|
|
32
|
+
color: var(--zx-module-glyph, var(--zx-module-fg-light));
|
|
33
|
+
font-size: calc(var(--zx-module-icon-size, 1.5rem) * 0.6);
|
|
34
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Tier-2 semantic tokens — dark theme, from the shadcn/ui preset `b2BVl11e4` (Zinc):
|
|
3
|
+
* Zinc-950 page, Zinc-900 cards and popovers, Zinc-800 muted fills, translucent white borders
|
|
4
|
+
* (10%) and inputs (15%), Zinc-400 muted text.
|
|
5
|
+
*
|
|
6
|
+
* The `[data-zx-theme="auto"]` block below repeats these assignments under a
|
|
7
|
+
* `prefers-color-scheme` query; CSS has no way to share a declaration block across a media
|
|
8
|
+
* boundary, so the two lists must be kept in sync.
|
|
9
|
+
*/
|
|
10
|
+
[data-zx-theme="dark"] {
|
|
11
|
+
color-scheme: dark;
|
|
12
|
+
--zx-color-bg-page: var(--zx-gray-950);
|
|
13
|
+
--zx-color-bg-surface: var(--zx-gray-900);
|
|
14
|
+
--zx-color-bg-raised: var(--zx-gray-800);
|
|
15
|
+
--zx-color-bg-control: color-mix(in srgb, var(--zx-gray-0) 5%, transparent);
|
|
16
|
+
--zx-color-bg-muted: var(--zx-gray-800);
|
|
17
|
+
--zx-color-bg-hover: color-mix(in srgb, var(--zx-gray-0) 8%, transparent);
|
|
18
|
+
--zx-color-bg-selected: color-mix(in srgb, var(--zx-green-400) 18%, var(--zx-gray-900));
|
|
19
|
+
--zx-color-bg-backdrop: color-mix(in srgb, var(--zx-gray-950) 75%, transparent);
|
|
20
|
+
--zx-color-border: color-mix(in srgb, var(--zx-gray-0) 10%, transparent);
|
|
21
|
+
--zx-color-border-strong: color-mix(in srgb, var(--zx-gray-0) 28%, transparent);
|
|
22
|
+
--zx-color-border-control: color-mix(in srgb, var(--zx-gray-0) 15%, transparent);
|
|
23
|
+
--zx-color-text: var(--zx-gray-50);
|
|
24
|
+
--zx-color-text-muted: var(--zx-gray-400);
|
|
25
|
+
--zx-color-text-placeholder: var(--zx-gray-500);
|
|
26
|
+
--zx-color-text-invert: var(--zx-gray-950);
|
|
27
|
+
--zx-color-accent: var(--zx-green-400);
|
|
28
|
+
--zx-color-accent-hover: var(--zx-green-300);
|
|
29
|
+
--zx-color-accent-active: var(--zx-green-500);
|
|
30
|
+
--zx-color-accent-subtle: color-mix(in srgb, var(--zx-green-400) 16%, var(--zx-gray-900));
|
|
31
|
+
--zx-color-on-accent: var(--zx-gray-950);
|
|
32
|
+
--zx-color-danger: var(--zx-red-400);
|
|
33
|
+
--zx-color-danger-bg: color-mix(in srgb, var(--zx-red-400) 16%, var(--zx-gray-900));
|
|
34
|
+
--zx-color-warning: var(--zx-amber-400);
|
|
35
|
+
--zx-color-warning-bg: color-mix(in srgb, var(--zx-amber-400) 16%, var(--zx-gray-900));
|
|
36
|
+
--zx-color-success: var(--zx-green-400);
|
|
37
|
+
--zx-color-success-bg: color-mix(in srgb, var(--zx-green-400) 16%, var(--zx-gray-900));
|
|
38
|
+
--zx-color-info: var(--zx-blue-400);
|
|
39
|
+
--zx-color-info-bg: color-mix(in srgb, var(--zx-blue-400) 16%, var(--zx-gray-900));
|
|
40
|
+
--zx-color-ring: var(--zx-color-accent);
|
|
41
|
+
--zx-focus-ring: 0 0 0 3px color-mix(in srgb, var(--zx-color-ring) 45%, transparent);
|
|
42
|
+
--zx-overlay-shadow: 0 12px 36px rgb(0 0 0 / 45%);
|
|
43
|
+
--zx-header-bg: var(--zx-gray-900);
|
|
44
|
+
--zx-header-text: var(--zx-gray-50);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
@media (prefers-color-scheme: dark) {
|
|
48
|
+
[data-zx-theme="auto"] {
|
|
49
|
+
color-scheme: dark;
|
|
50
|
+
--zx-color-bg-page: var(--zx-gray-950);
|
|
51
|
+
--zx-color-bg-surface: var(--zx-gray-900);
|
|
52
|
+
--zx-color-bg-raised: var(--zx-gray-800);
|
|
53
|
+
--zx-color-bg-control: color-mix(in srgb, var(--zx-gray-0) 5%, transparent);
|
|
54
|
+
--zx-color-bg-muted: var(--zx-gray-800);
|
|
55
|
+
--zx-color-bg-hover: color-mix(in srgb, var(--zx-gray-0) 8%, transparent);
|
|
56
|
+
--zx-color-bg-selected: color-mix(in srgb, var(--zx-green-400) 18%, var(--zx-gray-900));
|
|
57
|
+
--zx-color-bg-backdrop: color-mix(in srgb, var(--zx-gray-950) 75%, transparent);
|
|
58
|
+
--zx-color-border: color-mix(in srgb, var(--zx-gray-0) 10%, transparent);
|
|
59
|
+
--zx-color-border-strong: color-mix(in srgb, var(--zx-gray-0) 28%, transparent);
|
|
60
|
+
--zx-color-border-control: color-mix(in srgb, var(--zx-gray-0) 15%, transparent);
|
|
61
|
+
--zx-color-text: var(--zx-gray-50);
|
|
62
|
+
--zx-color-text-muted: var(--zx-gray-400);
|
|
63
|
+
--zx-color-text-placeholder: var(--zx-gray-500);
|
|
64
|
+
--zx-color-text-invert: var(--zx-gray-950);
|
|
65
|
+
--zx-color-accent: var(--zx-green-400);
|
|
66
|
+
--zx-color-accent-hover: var(--zx-green-300);
|
|
67
|
+
--zx-color-accent-active: var(--zx-green-500);
|
|
68
|
+
--zx-color-accent-subtle: color-mix(in srgb, var(--zx-green-400) 16%, var(--zx-gray-900));
|
|
69
|
+
--zx-color-on-accent: var(--zx-gray-950);
|
|
70
|
+
--zx-color-danger: var(--zx-red-400);
|
|
71
|
+
--zx-color-danger-bg: color-mix(in srgb, var(--zx-red-400) 16%, var(--zx-gray-900));
|
|
72
|
+
--zx-color-warning: var(--zx-amber-400);
|
|
73
|
+
--zx-color-warning-bg: color-mix(in srgb, var(--zx-amber-400) 16%, var(--zx-gray-900));
|
|
74
|
+
--zx-color-success: var(--zx-green-400);
|
|
75
|
+
--zx-color-success-bg: color-mix(in srgb, var(--zx-green-400) 16%, var(--zx-gray-900));
|
|
76
|
+
--zx-color-info: var(--zx-blue-400);
|
|
77
|
+
--zx-color-info-bg: color-mix(in srgb, var(--zx-blue-400) 16%, var(--zx-gray-900));
|
|
78
|
+
--zx-color-ring: var(--zx-color-accent);
|
|
79
|
+
--zx-focus-ring: 0 0 0 3px color-mix(in srgb, var(--zx-color-ring) 45%, transparent);
|
|
80
|
+
--zx-overlay-shadow: 0 12px 36px rgb(0 0 0 / 45%);
|
|
81
|
+
--zx-header-bg: var(--zx-gray-900);
|
|
82
|
+
--zx-header-text: var(--zx-gray-50);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Tier-1 palette and primitives.
|
|
3
|
+
*
|
|
4
|
+
* Derived from the shadcn/ui preset `b2BVl11e4` (style Nova · base colour Zinc · theme Zinc ·
|
|
5
|
+
* chart colour Emerald · Inter · radius small). The neutral ramp is Tailwind Zinc; the accent
|
|
6
|
+
* ramp is the preset's Emerald chart ramp, anchored at 400 to the ZeyOS brand green #21cc75.
|
|
7
|
+
*
|
|
8
|
+
* Only tier-2 semantic tokens (tokens/semantic.css, tokens/dark.css) may reference these.
|
|
9
|
+
* Component CSS must never use them directly — tests/lint-tokens.js enforces that.
|
|
10
|
+
*/
|
|
11
|
+
:root {
|
|
12
|
+
/* Neutrals — Tailwind Zinc */
|
|
13
|
+
--zx-gray-0: #ffffff;
|
|
14
|
+
--zx-gray-50: #fafafa;
|
|
15
|
+
--zx-gray-100: #f4f4f5;
|
|
16
|
+
--zx-gray-150: #ececee;
|
|
17
|
+
--zx-gray-200: #e4e4e7;
|
|
18
|
+
--zx-gray-300: #d4d4d8;
|
|
19
|
+
--zx-gray-400: #9f9fa9;
|
|
20
|
+
--zx-gray-500: #71717b;
|
|
21
|
+
--zx-gray-600: #52525c;
|
|
22
|
+
--zx-gray-700: #3f3f47;
|
|
23
|
+
--zx-gray-800: #27272a;
|
|
24
|
+
--zx-gray-900: #18181b;
|
|
25
|
+
--zx-gray-950: #09090b;
|
|
26
|
+
|
|
27
|
+
/* Accent — the preset's Emerald chart ramp, with the ZeyOS brand green at 400 */
|
|
28
|
+
--zx-green-300: #5ee9b5;
|
|
29
|
+
--zx-green-400: #21cc75;
|
|
30
|
+
--zx-green-500: #009966;
|
|
31
|
+
--zx-green-600: #007a55;
|
|
32
|
+
--zx-green-700: #006045;
|
|
33
|
+
|
|
34
|
+
/* Status */
|
|
35
|
+
--zx-red-400: #ff6467;
|
|
36
|
+
--zx-red-500: #e7000b;
|
|
37
|
+
--zx-red-600: #c10007;
|
|
38
|
+
--zx-amber-400: #ffb900;
|
|
39
|
+
--zx-amber-500: #fe9a00;
|
|
40
|
+
--zx-amber-600: #bb4d00;
|
|
41
|
+
--zx-blue-400: #51a2ff;
|
|
42
|
+
--zx-blue-500: #2b7fff;
|
|
43
|
+
--zx-blue-600: #155dfc;
|
|
44
|
+
|
|
45
|
+
--zx-space-1: 4px;
|
|
46
|
+
--zx-space-2: 8px;
|
|
47
|
+
--zx-space-3: 12px;
|
|
48
|
+
--zx-space-4: 16px;
|
|
49
|
+
--zx-space-5: 20px;
|
|
50
|
+
--zx-space-6: 24px;
|
|
51
|
+
--zx-space-7: 32px;
|
|
52
|
+
--zx-space-8: 40px;
|
|
53
|
+
|
|
54
|
+
/* Radius — the preset's `--radius: 0.45rem`, with shadcn's derived steps */
|
|
55
|
+
--zx-radius: 0.45rem;
|
|
56
|
+
--zx-radius-sm: calc(var(--zx-radius) - 4px);
|
|
57
|
+
--zx-radius-md: calc(var(--zx-radius) - 2px);
|
|
58
|
+
--zx-radius-lg: var(--zx-radius);
|
|
59
|
+
--zx-radius-xl: calc(var(--zx-radius) + 4px);
|
|
60
|
+
--zx-radius-full: 999px;
|
|
61
|
+
|
|
62
|
+
--zx-font-sans: Inter, "Inter Variable", ui-sans-serif, system-ui, -apple-system,
|
|
63
|
+
"Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
|
|
64
|
+
--zx-font-mono: "Geist Mono", ui-monospace, SFMono-Regular, "SF Mono", Menlo, Monaco,
|
|
65
|
+
Consolas, monospace;
|
|
66
|
+
--zx-text-xs: 12px;
|
|
67
|
+
--zx-text-sm: 13px;
|
|
68
|
+
--zx-text-md: 14px;
|
|
69
|
+
--zx-text-lg: 16px;
|
|
70
|
+
--zx-text-xl: 18px;
|
|
71
|
+
--zx-text-2xl: 24px;
|
|
72
|
+
|
|
73
|
+
--zx-shadow-1: 0 1px 2px 0 rgb(9 9 11 / 5%);
|
|
74
|
+
--zx-shadow-2: 0 1px 3px 0 rgb(9 9 11 / 10%), 0 1px 2px -1px rgb(9 9 11 / 10%);
|
|
75
|
+
--zx-shadow-3: 0 10px 15px -3px rgb(9 9 11 / 10%), 0 4px 6px -4px rgb(9 9 11 / 10%);
|
|
76
|
+
|
|
77
|
+
--zx-dur-fast: 120ms;
|
|
78
|
+
--zx-dur-base: 180ms;
|
|
79
|
+
--zx-ease: cubic-bezier(.2, .6, .3, 1);
|
|
80
|
+
}
|