ooxml-ui 0.12.0 → 0.14.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/README.md CHANGED
@@ -58,38 +58,38 @@ with an incompatible build of this package.
58
58
 
59
59
  ## Features: elements
60
60
 
61
- | Tag | Attributes / properties | Events (all bubble, composed) |
62
- | ----------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------- |
63
- | `office-ui-button` | `label`, `icon`, `command`, `disabled`, `pressed`, `expanded`, `icon-only`, `variant="stacked"`, `keyshortcuts` | `office-command` `{ command }` |
64
- | `office-ui-checkbox`, `office-ui-switch` | `checked`, `disabled`, `value`, `aria-label`; form-associated | `input`, `change` |
65
- | `office-ui-select` | `options` `[{ value, label, disabled? }]`, `value`, `selectedIndex`, `disabled` | `input`, `change` |
66
- | `office-ui-ribbon-group` | `label`, `launcher` (dialog launcher command), `launcher-disabled`; default slot | launcher: `office-command` `{ command }` |
67
- | `office-ui-ribbon-stack` | `orientation="horizontal"`; default slot (three-row column of small commands by default) | none |
68
- | `office-ui-menu-button` / `-menu-item` | button: `label`, `icon`, `command` (split button), `variant`, `disabled`, `keyshortcuts`; item: `command`, `label`, `icon`, `disabled`, `checked` | item choice: `office-command` `{ command }` |
69
- | `office-ui-toolbar` | `aria-label`, `aria-orientation`; arrow-key focus movement | none |
70
- | `office-ui-dialog` | `open`, `heading`, `dismissible="false"`, `show()`, `close()`; slots default, `footer` | `office-dialog-close` `{ reason }` (cancelable) |
71
- | `office-ui-status-bar` / `-status-item` | `label`, `value`, `interactive`, `id` | `office-status-activate` `{ id }` |
72
- | `office-ui-zoom-slider` | `value` (percent), `min`, `max`, `step`, `disabled`, `fit` (fit button name), `label` | `input`, `change`; fit: `office-command` `{ command: 'zoom-fit' }` |
73
- | `office-ui-tab-strip` | `tabs` `[{ id, label, title? }]`, `selected`, `label`, `previous-label`, `next-label`, `add-label`, `add-disabled`, `add-title`, `disabled` | `office-tab-select` `{ id }` (cancelable); add: `office-command` `{ command: 'tab-add' }` |
74
- | `office-ui-context-menu` / `office-ui-menu-separator` | `label`; `openAt(x, y)`, `close()`, `open`; `office-ui-menu-item` and separator children | item choice: `office-command` `{ command }` |
75
- | `office-ui-command-search` | `commands` `[{ id, label, keywords?, description?, disabled?, title? }]`, `placeholder`, `label`, `limit` (Office's "Tell me what you want to do") | choice: `office-command` `{ command }` |
76
- | `office-ui-options-dialog` | `categories` `[{ id, label, description?, disabled?, sections: [{ id, title, controls }] }]` (controls: `toggle`, `select`, `number`, `text`, each optionally `disabled` with a reason), `values`, `category`, `open`, `heading`, `show()`, `close()` | OK: `office-options-change` `{ values, changed }` |
77
- | `office-ui-account` | `profile` `{ displayName, avatarColor, initial? }`; slots `sign-in` and default (product sections) | `office-profile-change` `{ profile }` |
78
- | `office-ui-ribbon` | Tab row over tab panels. Panels are children with `data-ribbon-tab`, `data-label`, optional `data-tab-keytip`; slots `quick-access`, `search`, `end`; `selected`, `label`, `file-label`, `no-file`, `file-expanded`, `file-keytip`; `focusFile()`, `focusTab()` | `office-ribbon-select` `{ tab }` (cancelable), `office-ribbon-file` |
79
- | `office-ui-backstage` | `items` `[{ id, label, group?: 'footer', disabled?, title? }]`, `open`, `selected`, `label`, `back-label`, `show(page?)`, `close()`; pages are children with `data-backstage-page` | `office-backstage-select` `{ id }` (cancelable), `office-backstage-close` `{ reason }` (cancelable) |
80
- | `office-ui-find-bar` | `open`, `label`, `input-label`, `placeholder`, `maxlength`, `disabled`, `navigation-disabled`, `previous-label`, `next-label`, `close-label`; `value`, `status`, `statusTitle`, `show()`, `close()` | `office-find-input` `{ query }`, `office-find-step` `{ direction }`, `office-find-close` |
81
- | `office-ui-ruler` | `orientation="vertical"`, `origin` (px offset of zero), `scale` (px per unit, default 96), `direction="reverse"`; decorative | none |
82
- | `office-ui-print-preview` | `pages` (rendered nodes; an inert clone of the current one is shown), `index`, `label`, `empty-label` | `office-print-preview-page` `{ index }` |
83
- | `office-ui-radio` | `checked`, `disabled`, `value`, `name`; radios of one tag sharing a `name` form a roving-focus group; form-associated | `input`, `change` |
84
- | `office-ui-search` | `value`, `placeholder`, `disabled`, `aria-label`, `variant="titlebar"`; `focus()`, `select()` | `input`, `change` |
85
- | `office-ui-ribbon-toggle` | `label`, `checked`, `disabled`, `title`, `command` (a labelled ribbon checkbox row) | `office-toggle` `{ command, checked }` |
86
- | `office-ui-dialog-footer` | `state` `{ actions: [{ id, label, variant?, icon?, disabled?, busy?, title?, align?, testId? }] }`, `focusAction(id)` | `office-dialog-footer-request` `{ id }` |
87
- | `office-ui-toasts` | `state` `{ toasts: [{ id, code?, severity, message }], overflowCount?, labels? }`; hidden when empty, host positions it | `office-toasts-request` `{ id: 'dismiss', toastId }` or `{ id: 'dismissAll' }` |
88
- | `office-ui-read-only-banner` | `state` `{ kind, message, passwordPromptOpen?, passwordError?, checkingPassword?, labels? }` | `office-read-only-request` (Edit anyway, Dismiss, password submit or cancel) |
89
- | `office-ui-paste-options` | `state` `{ left, top, options: [{ id, label }], label? }`; fixed 4px past the pasted object | `office-paste-options-request` `{ format }`, `office-paste-options-dismiss` |
90
- | `office-ui-presence` | `participants`, `max`, `label` | `office-presence-select` `{ id }` |
91
- | `office-ui-smartart` | `drawing` (core `DiagramDrawing`), `schemeColors`, `label` | `office-smartart-render` (render report) |
92
- | `office-ui-icon` | `name`, `label` | none |
61
+ | Tag | Attributes / properties | Events (all bubble, composed) |
62
+ | ----------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- |
63
+ | `office-ui-button` | `label`, `icon`, `command`, `disabled`, `pressed`, `expanded`, `icon-only`, `variant="stacked"`, `keyshortcuts` | `office-command` `{ command }` |
64
+ | `office-ui-checkbox`, `office-ui-switch` | `checked`, `disabled`, `value`, `aria-label`; form-associated | `input`, `change` |
65
+ | `office-ui-select` | `<option>` / `<optgroup>` children (`data-display-label`, `data-description`, font previews) or the `options` property `[{ value, label, disabled? }]`; `value`, `selectedIndex`, `disabled`, `aria-label`, `variant="ribbon-font" | "ribbon-icon"`, `data-font-picker`; `icon`and`custom` slots; arrows, Home, End, PageUp/PageDown, typeahead | `input`, `change` |
66
+ | `office-ui-ribbon-group` | `label`, `launcher` (dialog launcher command), `launcher-disabled`; default slot | launcher: `office-command` `{ command }` |
67
+ | `office-ui-ribbon-stack` | `orientation="horizontal"`; default slot (three-row column of small commands by default) | none |
68
+ | `office-ui-menu-button` / `-menu-item` | button: `label`, `icon`, `command` (split button), `variant`, `disabled`, `keyshortcuts`; item: `command`, `label`, `icon`, `disabled`, `checked` | item choice: `office-command` `{ command }` |
69
+ | `office-ui-toolbar` | `aria-label`, `aria-orientation`; arrow-key focus movement | none |
70
+ | `office-ui-dialog` | `open`, `heading`, `dismissible="false"`, `show()`, `close()`; slots default, `footer` | `office-dialog-close` `{ reason }` (cancelable) |
71
+ | `office-ui-status-bar` / `-status-item` | `label`, `value`, `interactive`, `id` | `office-status-activate` `{ id }` |
72
+ | `office-ui-zoom-slider` | `value` (percent), `min`, `max`, `step`, `disabled`, `fit` (fit button name), `label` | `input`, `change`; fit: `office-command` `{ command: 'zoom-fit' }` |
73
+ | `office-ui-tab-strip` | `tabs` `[{ id, label, title? }]`, `selected`, `label`, `previous-label`, `next-label`, `add-label`, `add-disabled`, `add-title`, `disabled` | `office-tab-select` `{ id }` (cancelable); add: `office-command` `{ command: 'tab-add' }` |
74
+ | `office-ui-context-menu` / `office-ui-menu-separator` | `label`; `openAt(x, y)`, `close()`, `open`; `office-ui-menu-item` and separator children | item choice: `office-command` `{ command }` |
75
+ | `office-ui-command-search` | `commands` `[{ id, label, keywords?, description?, disabled?, title? }]`, `placeholder`, `label`, `limit` (Office's "Tell me what you want to do") | choice: `office-command` `{ command }` |
76
+ | `office-ui-options-dialog` | `categories` `[{ id, label, description?, disabled?, sections: [{ id, title, controls }] }]` (controls: `toggle`, `select`, `number`, `text`, each optionally `disabled` with a reason), `values`, `category`, `open`, `heading`, `show()`, `close()` | OK: `office-options-change` `{ values, changed }` |
77
+ | `office-ui-account` | `profile` `{ displayName, avatarColor, initial? }`; slots `sign-in` and default (product sections) | `office-profile-change` `{ profile }` |
78
+ | `office-ui-ribbon` | Tab row over tab panels. Panels are children with `data-ribbon-tab`, `data-label`, optional `data-tab-keytip`; slots `quick-access`, `search`, `end`; `selected`, `label`, `file-label`, `no-file`, `file-expanded`, `file-keytip`; `focusFile()`, `focusTab()` | `office-ribbon-select` `{ tab }` (cancelable), `office-ribbon-file` |
79
+ | `office-ui-backstage` | `items` `[{ id, label, group?: 'footer', disabled?, title? }]`, `open`, `selected`, `label`, `back-label`, `show(page?)`, `close()`; pages are children with `data-backstage-page` | `office-backstage-select` `{ id }` (cancelable), `office-backstage-close` `{ reason }` (cancelable) |
80
+ | `office-ui-find-bar` | `open`, `label`, `input-label`, `placeholder`, `maxlength`, `disabled`, `navigation-disabled`, `previous-label`, `next-label`, `close-label`; `value`, `status`, `statusTitle`, `show()`, `close()` | `office-find-input` `{ query }`, `office-find-step` `{ direction }`, `office-find-close` |
81
+ | `office-ui-ruler` | `orientation="vertical"`, `origin` (px offset of zero), `scale` (px per unit, default 96), `direction="reverse"`; decorative | none |
82
+ | `office-ui-print-preview` | `pages` (rendered nodes; an inert clone of the current one is shown), `index`, `label`, `empty-label` | `office-print-preview-page` `{ index }` |
83
+ | `office-ui-radio` | `checked`, `disabled`, `value`, `name`; radios of one tag sharing a `name` form a roving-focus group; form-associated | `input`, `change` |
84
+ | `office-ui-search` | `value`, `placeholder`, `disabled`, `aria-label`, `variant="titlebar"`; `focus()`, `select()` | `input`, `change` |
85
+ | `office-ui-ribbon-toggle` | `label`, `checked`, `disabled`, `title`, `command` (a labelled ribbon checkbox row) | `office-toggle` `{ command, checked }` |
86
+ | `office-ui-dialog-footer` | `state` `{ actions: [{ id, label, variant?, icon?, disabled?, busy?, title?, align?, testId? }] }`, `focusAction(id)` | `office-dialog-footer-request` `{ id }` |
87
+ | `office-ui-toasts` | `state` `{ toasts: [{ id, code?, severity, message }], overflowCount?, labels? }`; hidden when empty, host positions it | `office-toasts-request` `{ id: 'dismiss', toastId }` or `{ id: 'dismissAll' }` |
88
+ | `office-ui-read-only-banner` | `state` `{ kind, message, passwordPromptOpen?, passwordError?, checkingPassword?, labels? }` | `office-read-only-request` (Edit anyway, Dismiss, password submit or cancel) |
89
+ | `office-ui-paste-options` | `state` `{ left, top, options: [{ id, label }], label? }`; fixed 4px past the pasted object | `office-paste-options-request` `{ format }`, `office-paste-options-dismiss` |
90
+ | `office-ui-presence` | `participants`, `max`, `label` | `office-presence-select` `{ id }` |
91
+ | `office-ui-smartart` | `drawing` (core `DiagramDrawing`), `schemeColors`, `label` | `office-smartart-render` (render report) |
92
+ | `office-ui-icon` | `name`, `label` | none |
93
93
 
94
94
  The local profile behind `office-ui-account` is stored on the device only, under one suite-wide
95
95
  key (`readOfficeProfile`, `writeOfficeProfile`, `clearOfficeProfile`), so every Office viewer on
@@ -104,8 +104,29 @@ Elements with intent events read their event name and test-id prefix from static
104
104
 
105
105
  Setting a property never emits an event; only user activation does. Controls honour
106
106
  `prefers-color-scheme`, `forced-colors: active` (system colours and a visible focus ring) and
107
- coarse pointers (44px targets through `--office-target-size`). Tokens are the `--office-*`
108
- custom properties in `THEME_CSS`; override them on `:root` or any container.
107
+ coarse pointers (44px targets through `--office-target-size`).
108
+
109
+ ## Design tokens
110
+
111
+ Every control is token based: no colour, length, radius, font size, shadow, duration or layer
112
+ is written literally. `OFFICE_TOKENS` (from `ooxml-ui/theme`) is the single table of
113
+ `--office-*` tokens and their defaults; controls read them through `tok(name)`, which expands to
114
+ `var(--office-…, <default>)`, so they render correctly with or without the installed theme.
115
+ `THEME_CSS` declares every default on `:root`, plus dark-mode and forced-colours values. Override
116
+ any token on `:root` or on any container to retheme or resize the suite:
117
+
118
+ - semantic colours: `--office-foreground`, `-background`, `-surface`, `-selected`, `-border`,
119
+ `-accent`, `-accent-foreground`, `-ring`, `-danger`, `-warning`, `-info`, `-popover`, `-overlay`,
120
+ `-notice-*`, `-paper`;
121
+ - scales: `--office-space-*`, `--office-radius-*`, `--office-font-size-*`, `--office-icon-size-*`,
122
+ `--office-control-height-*`, `--office-shadow-*`, `--office-duration-*`, `--office-z-*`;
123
+ - component tokens that default to the scales, for example `--office-checkbox-size`,
124
+ `--office-switch-width`, `--office-ribbon-tab-height`, `--office-backstage-nav-width` and
125
+ `--office-dialog-max-width`.
126
+
127
+ Only the two layout breakpoints (`COMPACT`, `TOUCH`) are literal, because CSS does not allow
128
+ custom properties in media queries. A test fails when any control's stylesheet contains a raw
129
+ colour or length outside a token, or references an undeclared token.
109
130
 
110
131
  `office-ui-smartart` shows the drawing the producing application cached; it never lays out a
111
132
  diagram itself. Preset outlines it cannot draw are rendered as rectangles, gradient and pattern
@@ -1,3 +1,5 @@
1
+ import { TOUCH, tok } from './chunk-BDJW2KDI.js';
2
+
1
3
  // src/registry.ts
2
4
  var CONTRACT_REVISION = 1;
3
5
  var CONTRACT_KEY = /* @__PURE__ */ Symbol.for("office-ui.web-control-contract");
@@ -60,11 +62,11 @@ function attachStyles(root, css) {
60
62
  }
61
63
  var COMMON_CONTROL_CSS = `
62
64
  :host([hidden]) { display: none !important; }
63
- @media (pointer: coarse), (max-width: 767px) {
64
- :host { --office-target-size: 44px; }
65
+ @media ${TOUCH} {
66
+ :host { --office-target-size: ${tok("--office-target-size-touch")}; }
65
67
  }
66
68
  @media (forced-colors: active) {
67
- :host(:focus-visible), :focus-visible { outline: 2px solid Highlight; outline-offset: 2px; }
69
+ :host(:focus-visible), :focus-visible { outline: ${tok("--office-focus-width")} solid Highlight; outline-offset: ${tok("--office-focus-offset")}; }
68
70
  }
69
71
  `;
70
72
  var controlCss = (css) => `${COMMON_CONTROL_CSS}
@@ -1,4 +1,5 @@
1
- import { definer, attachStyles, controlCss, emit } from './chunk-EY266IK3.js';
1
+ import { definer, attachStyles, controlCss, emit } from './chunk-3BHP4IFP.js';
2
+ import { tok } from './chunk-BDJW2KDI.js';
2
3
  import { normalizeHexColor } from 'ooxml-core/color';
3
4
 
4
5
  var SVG_NS = "http://www.w3.org/2000/svg";
@@ -155,8 +156,8 @@ function textElement(doc, shape, scheme) {
155
156
  var CSS = `
156
157
  :host { display: block; }
157
158
  svg { display: block; width: 100%; height: auto; max-height: 100%; }
158
- text { font-family: var(--office-font, system-ui, sans-serif); pointer-events: none; }
159
- .empty { padding: 8px; font-size: 12px; color: var(--office-muted-foreground, #6b7280); }
159
+ text { font-family: ${tok("--office-font")}; pointer-events: none; }
160
+ .empty { padding: ${tok("--office-space-2")}; font-size: ${tok("--office-font-size-sm")}; color: ${tok("--office-muted-foreground")}; }
160
161
  @media (forced-colors: active) { text { fill: CanvasText; } }
161
162
  `;
162
163
  var defineSmartArt = definer("office-ui-smartart", () => {
@@ -1,3 +1,5 @@
1
+ import { OFFICE_TOKENS, TOUCH } from './chunk-BDJW2KDI.js';
2
+
1
3
  // src/theme.ts
2
4
  var THEME_STYLE_ID = "office-ui-theme";
3
5
  var DARK = `
@@ -8,21 +10,19 @@ var DARK = `
8
10
  --office-border: #374151;
9
11
  --office-accent: #6366f1;
10
12
  --office-ring: #818cf8;
11
- --office-danger: #f87171;`;
13
+ --office-danger: #f87171;
14
+ --office-selected: #374151;
15
+ --office-notice-background: rgb(120 53 15 / 20%);
16
+ --office-notice-foreground: #fde68a;
17
+ --office-notice-accent: #fbbf24;
18
+ --office-info: #60a5fa;
19
+ --office-warning: #f59e0b;
20
+ --office-shadow: 0 6px 20px rgb(0 0 0 / 45%);
21
+ --office-shadow-lg: 0 10px 25px rgb(0 0 0 / 45%);`;
22
+ var LIGHT = Object.entries(OFFICE_TOKENS).map(([name, value]) => ` ${name}: ${value};`).join("\n");
12
23
  var THEME_CSS = `
13
24
  :root {
14
- --office-foreground: #1f2937;
15
- --office-muted-foreground: #6b7280;
16
- --office-background: #ffffff;
17
- --office-surface: #f3f4f6;
18
- --office-border: #d1d5db;
19
- --office-accent: #2563eb;
20
- --office-accent-foreground: #ffffff;
21
- --office-ring: #2563eb;
22
- --office-danger: #b91c1c;
23
- --office-target-size: 28px;
24
- --office-radius: 4px;
25
- --office-font: system-ui, -apple-system, "Segoe UI", sans-serif;
25
+ ${LIGHT}
26
26
  }
27
27
  @media (prefers-color-scheme: dark) {
28
28
  :root:not([data-office-theme="light"]) {${DARK}
@@ -30,8 +30,8 @@ var THEME_CSS = `
30
30
  }
31
31
  :root[data-office-theme="dark"] {${DARK}
32
32
  }
33
- @media (pointer: coarse), (max-width: 767px) {
34
- :root { --office-target-size: 44px; }
33
+ @media ${TOUCH} {
34
+ :root { --office-target-size: var(--office-target-size-touch); }
35
35
  }
36
36
  @media (forced-colors: active) {
37
37
  :root {
@@ -0,0 +1,196 @@
1
+ // src/tokens.ts
2
+ var OFFICE_TOKENS = {
3
+ // Colour: semantic
4
+ "--office-foreground": "#1f2937",
5
+ "--office-muted-foreground": "#6b7280",
6
+ "--office-background": "#ffffff",
7
+ "--office-surface": "#f3f4f6",
8
+ "--office-selected": "#e5e7eb",
9
+ "--office-border": "#d1d5db",
10
+ "--office-accent": "#2563eb",
11
+ "--office-accent-foreground": "#ffffff",
12
+ "--office-ring": "#2563eb",
13
+ "--office-danger": "#b91c1c",
14
+ "--office-danger-foreground": "#ffffff",
15
+ "--office-warning": "#d97706",
16
+ "--office-warning-foreground": "#ffffff",
17
+ "--office-info": "#3b82f6",
18
+ "--office-popover": "var(--office-background, #ffffff)",
19
+ "--office-popover-foreground": "var(--office-foreground, #1f2937)",
20
+ "--office-overlay": "rgb(0 0 0 / 40%)",
21
+ "--office-notice-background": "#fef3c7",
22
+ "--office-notice-foreground": "#78350f",
23
+ "--office-notice-border": "rgb(180 83 9 / 30%)",
24
+ "--office-notice-accent": "#d97706",
25
+ "--office-keytip-background": "#ffffff",
26
+ "--office-keytip-foreground": "#1f1f1f",
27
+ "--office-keytip-border": "#8a8886",
28
+ "--office-highlight": "#dc2626",
29
+ "--office-paper": "#ffffff",
30
+ "--office-accent-hover": "color-mix(in srgb, var(--office-accent, #2563eb) 85%, #000)",
31
+ // Typography
32
+ "--office-font": 'system-ui, -apple-system, "Segoe UI", sans-serif',
33
+ "--office-font-size-3xs": "9px",
34
+ "--office-font-size-2xs": "10px",
35
+ "--office-font-size-xs": "11px",
36
+ "--office-font-size-sm": "12px",
37
+ "--office-font-size": "13px",
38
+ "--office-font-size-md": "14px",
39
+ "--office-font-size-lg": "15px",
40
+ "--office-font-size-xl": "18px",
41
+ "--office-font-weight-medium": "500",
42
+ "--office-font-weight-bold": "600",
43
+ "--office-line-height": "1.4",
44
+ "--office-line-height-tight": "1.2",
45
+ "--office-icon-stroke": "1.5",
46
+ // Space
47
+ "--office-space-px": "1px",
48
+ "--office-space-0": "2px",
49
+ "--office-space-1": "4px",
50
+ "--office-space-1-5": "6px",
51
+ "--office-space-2": "8px",
52
+ "--office-space-2-5": "10px",
53
+ "--office-space-3": "12px",
54
+ "--office-space-3-5": "14px",
55
+ "--office-space-4": "16px",
56
+ "--office-space-5": "20px",
57
+ "--office-space-6": "24px",
58
+ // Shape
59
+ "--office-border-width": "1px",
60
+ "--office-border-width-thick": "2px",
61
+ "--office-radius-xs": "2px",
62
+ "--office-radius-sm": "3px",
63
+ "--office-radius": "4px",
64
+ "--office-radius-md": "6px",
65
+ "--office-radius-lg": "8px",
66
+ "--office-radius-full": "999px",
67
+ // Focus
68
+ "--office-focus-width": "2px",
69
+ "--office-focus-offset": "2px",
70
+ // Sizes
71
+ "--office-target-size": "28px",
72
+ "--office-target-size-touch": "44px",
73
+ "--office-control-height": "24px",
74
+ "--office-control-height-md": "28px",
75
+ "--office-control-height-lg": "32px",
76
+ "--office-input-height": "26px",
77
+ "--office-control-height-xs": "22px",
78
+ "--office-icon-size-xs": "10px",
79
+ "--office-icon-size-sm": "12px",
80
+ "--office-icon-size": "14px",
81
+ "--office-icon-size-md": "16px",
82
+ "--office-icon-size-ml": "18px",
83
+ "--office-icon-size-lg": "20px",
84
+ // Elevation and layering
85
+ "--office-shadow-sm": "0 1px 3px rgb(0 0 0 / 20%)",
86
+ "--office-shadow": "0 6px 20px rgb(0 0 0 / 18%)",
87
+ "--office-shadow-lg": "0 10px 25px rgb(0 0 0 / 20%)",
88
+ "--office-z-popover": "1100",
89
+ "--office-z-dialog": "1000",
90
+ "--office-z-backstage": "30",
91
+ // Motion
92
+ "--office-duration-fast": ".12s",
93
+ "--office-duration": ".15s",
94
+ "--office-duration-spin": ".8s",
95
+ // Component: fields
96
+ "--office-field-height": "28px",
97
+ "--office-field-height-lg": "40px",
98
+ "--office-field-radius": "5px",
99
+ "--office-field-border": "var(--office-border, #d1d5db)",
100
+ "--office-field-border-focus": "var(--office-ring, #2563eb)",
101
+ "--office-field-background": "var(--office-background, #ffffff)",
102
+ "--office-field-foreground": "var(--office-foreground, #1f2937)",
103
+ "--office-field-placeholder": "var(--office-muted-foreground, #6b7280)",
104
+ // Component: checkbox, radio, switch
105
+ "--office-checkbox-size": "16px",
106
+ "--office-checkbox-size-touch": "22px",
107
+ "--office-checkbox-radius": "3px",
108
+ "--office-checkbox-border": "var(--office-border, #d1d5db)",
109
+ "--office-checkbox-background": "var(--office-background, #ffffff)",
110
+ "--office-checkbox-accent": "var(--office-accent, #2563eb)",
111
+ "--office-checkbox-accent-foreground": "var(--office-accent-foreground, #ffffff)",
112
+ "--office-radio-dot-size": "8px",
113
+ "--office-radio-dot-size-touch": "12px",
114
+ "--office-switch-width": "32px",
115
+ "--office-switch-height": "18px",
116
+ "--office-switch-width-touch": "44px",
117
+ "--office-switch-height-touch": "24px",
118
+ "--office-switch-border-width": "1px",
119
+ "--office-switch-knob-size": "12px",
120
+ "--office-switch-knob-size-touch": "18px",
121
+ "--office-switch-knob-offset": "2px",
122
+ "--office-switch-border": "var(--office-border, #d1d5db)",
123
+ "--office-switch-track": "var(--office-surface, #f3f4f6)",
124
+ "--office-switch-track-on": "var(--office-accent, #2563eb)",
125
+ "--office-switch-thumb": "var(--office-foreground, #1f2937)",
126
+ "--office-switch-thumb-on": "var(--office-accent-foreground, #ffffff)",
127
+ // Component: ribbon, status bar, tabs
128
+ "--office-ribbon-tab-height": "35px",
129
+ "--office-ribbon-group-gap": "2px",
130
+ "--office-ribbon-group-height": "78px",
131
+ "--office-ribbon-caption-line-height": "12px",
132
+ "--office-ribbon-row-height": "22px",
133
+ "--office-ribbon-file-min-width": "52px",
134
+ "--office-launcher-width": "16px",
135
+ "--office-launcher-height": "14px",
136
+ "--office-tab-indicator-width": "2.5px",
137
+ "--office-status-bar-height": "24px",
138
+ "--office-tab-height": "28px",
139
+ "--office-tab-max-width": "220px",
140
+ "--office-zoom-slider-width": "120px",
141
+ "--office-zoom-slider-min-width": "48px",
142
+ "--office-zoom-value-width": "40px",
143
+ // Component: panels and dialogs
144
+ "--office-dialog-width": "auto",
145
+ "--office-dialog-max-width": "min(640px, 100vw)",
146
+ "--office-dialog-max-height": "90vh",
147
+ "--office-dialog-min-width": "min(320px, 100vw)",
148
+ "--office-dialog-button-min-width": "76px",
149
+ "--office-options-width": "min(820px, 100vw)",
150
+ "--office-options-nav-width": "180px",
151
+ "--office-options-min-height": "min(440px, 70vh)",
152
+ "--office-options-label-width": "180px",
153
+ "--office-options-row-height": "30px",
154
+ "--office-options-number-width": "80px",
155
+ "--office-info-size": "15px",
156
+ "--office-selection-bar-width": "3px",
157
+ "--office-backstage-nav-width": "200px",
158
+ "--office-backstage-nav-background": "var(--office-accent, #2563eb)",
159
+ "--office-backstage-nav-foreground": "var(--office-accent-foreground, #ffffff)",
160
+ "--office-backstage-item-hover": "rgb(0 0 0 / 22%)",
161
+ "--office-backstage-padding": "28px 40px",
162
+ "--office-backstage-back-size": "36px",
163
+ "--office-backstage-item-height": "38px",
164
+ "--office-menu-min-width": "180px",
165
+ "--office-menu-max-height": "60vh",
166
+ "--office-context-menu-min-width": "200px",
167
+ "--office-search-popup-min-width": "240px",
168
+ "--office-search-popup-max-height": "320px",
169
+ "--office-select-max-height": "240px",
170
+ "--office-select-background": "var(--office-background, #ffffff)",
171
+ "--office-select-menu-min-width": "90px",
172
+ "--office-select-option-active": "color-mix(in srgb, var(--office-accent, #2563eb) 20%, var(--office-popover, #ffffff))",
173
+ "--office-select-ribbon-menu-width": "192px",
174
+ "--office-font-picker-max-height": "320px",
175
+ "--office-font-picker-width": "256px",
176
+ "--office-chevron-size": "6px",
177
+ "--office-ribbon-combo-height": "28px",
178
+ "--office-ribbon-icon-select-width": "36px",
179
+ "--office-search-width": "320px",
180
+ "--office-print-preview-width": "420px",
181
+ "--office-find-max-width": "640px",
182
+ "--office-find-bar-height": "40px",
183
+ "--office-ruler-size": "18px",
184
+ "--office-avatar-size": "48px",
185
+ "--office-avatar-color": "var(--office-muted-foreground, #6b7280)",
186
+ "--office-toast-width": "360px",
187
+ "--office-account-field-width": "320px"
188
+ };
189
+ function tok(name) {
190
+ return `var(${name}, ${OFFICE_TOKENS[name]})`;
191
+ }
192
+ var FOCUS_RING = `outline: ${tok("--office-focus-width")} solid ${tok("--office-ring")}; outline-offset: ${tok("--office-focus-offset")};`;
193
+ var COMPACT = "(max-width: 767px)";
194
+ var TOUCH = `(pointer: coarse), ${COMPACT}`;
195
+
196
+ export { COMPACT, FOCUS_RING, OFFICE_TOKENS, TOUCH, tok };