@parallelworks/ui 0.53.0 → 0.55.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/README.md +68 -9
  2. package/dist/access/AccessDrawer.d.ts +55 -0
  3. package/dist/access/AccessDrawer.js +445 -0
  4. package/dist/access/AccessList.d.ts +58 -0
  5. package/dist/access/AccessList.js +382 -0
  6. package/dist/access/GrantView.d.ts +35 -0
  7. package/dist/access/GrantView.js +188 -0
  8. package/dist/access/GroupPicker.d.ts +35 -0
  9. package/dist/access/GroupPicker.js +336 -0
  10. package/dist/access/focus.d.ts +10 -0
  11. package/dist/access/focus.js +27 -0
  12. package/dist/access/index.d.ts +3 -0
  13. package/dist/access/index.js +3 -0
  14. package/dist/access/model.d.ts +49 -0
  15. package/dist/access/model.js +129 -0
  16. package/dist/access/strings.d.ts +122 -0
  17. package/dist/access/strings.js +151 -0
  18. package/dist/access/types.d.ts +56 -0
  19. package/dist/ai/components/SlashMenu.js +1 -1
  20. package/dist/components/Combobox.d.ts +19 -0
  21. package/dist/components/Combobox.js +101 -50
  22. package/dist/components/DatePicker.js +4 -5
  23. package/dist/components/Drawer.d.ts +6 -1
  24. package/dist/components/Drawer.js +25 -16
  25. package/dist/components/Field.d.ts +8 -3
  26. package/dist/components/Field.js +32 -12
  27. package/dist/components/InfoTip.d.ts +3 -1
  28. package/dist/components/InfoTip.js +2 -1
  29. package/dist/components/Menu.js +4 -4
  30. package/dist/components/MenuEntries.js +1 -1
  31. package/dist/components/OptionDescription.d.ts +7 -0
  32. package/dist/components/OptionDescription.js +19 -0
  33. package/dist/components/Popover.d.ts +4 -1
  34. package/dist/components/Popover.js +2 -2
  35. package/dist/components/Provider.d.ts +7 -0
  36. package/dist/components/Provider.js +3 -0
  37. package/dist/components/Select.js +13 -11
  38. package/dist/components/comboboxItems.d.ts +10 -0
  39. package/dist/components/comboboxItems.js +8 -1
  40. package/dist/components/floating.d.ts +5 -2
  41. package/dist/components/floating.js +2 -2
  42. package/dist/editor/EditorField.js +1 -2
  43. package/dist/editor/Monaco.js +26 -2
  44. package/dist/editor/themes.d.ts +5 -0
  45. package/dist/editor/themes.js +18 -3
  46. package/dist/file-explorer/FileExplorer.js +2 -1
  47. package/dist/file-explorer/lib/paging.d.ts +1 -0
  48. package/dist/file-explorer/lib/paging.js +5 -1
  49. package/dist/index.d.ts +1 -1
  50. package/dist/index.js +2 -2
  51. package/dist/styles/theme.css +82 -62
  52. package/dist/styles.css +1 -1
  53. package/dist/theme/derive.d.ts +5 -3
  54. package/dist/theme/derive.js +74 -4
  55. package/package.json +6 -2
@@ -1,4 +1,4 @@
1
- import { type CodeStyle, type Scheme } from './model.js';
1
+ import { type CodeStyle, type Mode, type Scheme } from './model.js';
2
2
  export declare const THEME_TOKENS: readonly ['--theme-app-bg', '--theme-panel-bg', '--theme-panel-hover', '--theme-muted-panel-bg', '--theme-hover', '--theme-input-bg', '--theme-input-disabled-bg', '--theme-app', '--theme-muted-text-color', '--theme-placeholder', '--theme-link', '--theme-border', '--theme-border-strong', '--theme-accent', '--theme-accent-text', '--theme-accent-hover', '--theme-accent-subtle', '--theme-focus', '--theme-focus-ring', '--theme-success', '--theme-success-text', '--theme-success-solid', '--theme-success-muted', '--theme-error', '--theme-error-text', '--theme-error-solid', '--theme-error-muted', '--theme-warning', '--theme-warning-text', '--theme-warning-solid', '--theme-warning-muted', '--theme-info', '--theme-info-text', '--theme-info-solid', '--theme-info-muted', '--theme-favorite', '--theme-favorite-text', '--theme-favorite-solid', '--theme-favorite-muted', '--theme-shadow-sm', '--theme-shadow', '--theme-shadow-lg', '--theme-shadow-xl', '--theme-sidebar-bg', '--theme-sidebar-text', '--theme-sidebar-hover', '--theme-sidebar-active-bg', '--theme-sidebar-active-text', '--theme-code-bg', '--theme-code-text', '--theme-code-comment', '--theme-code-keyword', '--theme-code-string', '--theme-code-number', '--theme-code-function', '--theme-code-type', '--theme-code-property', '--theme-ansi-black', '--theme-ansi-red', '--theme-ansi-green', '--theme-ansi-yellow', '--theme-ansi-blue', '--theme-ansi-magenta', '--theme-ansi-cyan', '--theme-ansi-white'];
3
3
  export type ThemeToken = (typeof THEME_TOKENS)[number];
4
4
  export type ThemeVariables = Record<ThemeToken, string>;
@@ -22,7 +22,9 @@ export declare function generateTheme(scheme: Scheme, options?: DeriveOptions):
22
22
  /** Every `--theme-*` token for a scheme, in sRGB. */
23
23
  export declare function deriveTheme(scheme: Scheme, options?: DeriveOptions): ThemeVariables;
24
24
  /** A stylesheet for a scheme: sRGB under `selector`, and the display-p3 overrides under
25
- * `@media (color-gamut: p3)`. `omit` leaves tokens out, such as ones a host supplies. */
26
- export declare function themeStylesheet(selector: string, scheme: Scheme, options?: DeriveOptions & {
25
+ * `@media (color-gamut: p3)`. Given a scheme for each mode, every token that differs between
26
+ * them is written as `light-dark()`, so the tokens follow the CSS color-scheme wherever they are
27
+ * used. `omit` leaves tokens out, such as ones a host supplies. */
28
+ export declare function themeStylesheet(selector: string, scheme: Scheme | Record<Mode, Scheme>, options?: DeriveOptions & {
27
29
  omit?: readonly ThemeToken[];
28
30
  }): string;
@@ -159,6 +159,12 @@ var WHITE = {
159
159
  c: 0,
160
160
  h: 0
161
161
  };
162
+ /** The WCAG contrast a dark mode's hover keeps against the page at contrast 0, 30 and 100. */
163
+ var HOVER_STEP = [
164
+ 1.45,
165
+ 1.6,
166
+ 1.9
167
+ ];
162
168
  var STATUS = {
163
169
  success: 150,
164
170
  error: 27,
@@ -271,7 +277,13 @@ function build(scheme, options) {
271
277
  set("--theme-app-bg", base);
272
278
  set("--theme-panel-hover", neutral(set("--theme-panel-bg", raised(.85, .035)).l + dir * (dark ? .04 : .025) * s, 1));
273
279
  const mutedPanel = set("--theme-muted-panel-bg", step(.03, .065));
274
- set("--theme-hover", step(.045, .08));
280
+ const hoverStep = step(.045, .08);
281
+ const hoverGoal = dark ? solve(hoverStep, [toHex(base)], { wcag: byContrast(k, HOVER_STEP) }) : hoverStep;
282
+ const hoverAt = (share) => ({
283
+ ...hoverStep,
284
+ l: hoverStep.l + (hoverGoal.l - hoverStep.l) * share
285
+ });
286
+ set("--theme-hover", hoverAt(roomFor(hoverAt, { wcag: t.primary.wcag })));
275
287
  set("--theme-input-bg", raised(.7, .05));
276
288
  set("--theme-input-disabled-bg", step(.02, .025));
277
289
  set("--theme-accent-subtle", {
@@ -492,11 +504,69 @@ function compositeHex(fill, backdrop) {
492
504
  function deriveTheme(scheme, options = {}) {
493
505
  return build(scheme, options).srgb;
494
506
  }
507
+ var COLOR = /#[0-9a-f]{3,8}\b|rgba?\([^)]*\)|color\([^)]*\)/gi;
508
+ /** One value for both modes: each color that differs becomes `light-dark()`, which follows the
509
+ * CSS color-scheme. A shadow keeps its geometry and pairs its colors. */
510
+ function lightDark(light, dark) {
511
+ if (light === dark) return light;
512
+ const darks = dark.match(COLOR) ?? [];
513
+ if (light.replace(COLOR, "") !== dark.replace(COLOR, "")) throw new Error(`cannot pair ${light} with ${dark}`);
514
+ let i = 0;
515
+ return light.replace(COLOR, (color) => {
516
+ const other = darks[i++];
517
+ return color === other ? color : `light-dark(${color}, ${other})`;
518
+ });
519
+ }
520
+ /** Splits at the commas outside any parentheses. */
521
+ function topLevel(value) {
522
+ const parts = [];
523
+ let depth = 0;
524
+ let start = 0;
525
+ for (let i = 0; i < value.length; i++) {
526
+ const ch = value[i];
527
+ if (ch === "(") depth++;
528
+ else if (ch === ")") depth--;
529
+ else if (ch === "," && depth === 0) {
530
+ parts.push(value.slice(start, i).trim());
531
+ start = i + 1;
532
+ }
533
+ }
534
+ parts.push(value.slice(start).trim());
535
+ return parts;
536
+ }
537
+ /** A declaration laid out as the repository's formatter lays out CSS past 100 columns: a list
538
+ * takes a line per item, and a single function a line per argument. */
539
+ function declaration(token, value, indent) {
540
+ const line = `${indent}${token}: ${value};`;
541
+ if (line.length <= 100) return line;
542
+ const inner = `${indent} `;
543
+ const items = topLevel(value);
544
+ if (items.length > 1) return `${indent}${token}:\n${items.map((item) => `${inner}${item}`).join(",\n")};`;
545
+ const call = /^([\w-]+)\((.*)\)$/s.exec(value);
546
+ if (!call) return line;
547
+ const args = topLevel(call[2]);
548
+ return `${indent}${token}: ${call[1]}(\n${args.map((arg) => `${inner}${arg}`).join(",\n")}\n${indent});`;
549
+ }
495
550
  /** A stylesheet for a scheme: sRGB under `selector`, and the display-p3 overrides under
496
- * `@media (color-gamut: p3)`. `omit` leaves tokens out, such as ones a host supplies. */
551
+ * `@media (color-gamut: p3)`. Given a scheme for each mode, every token that differs between
552
+ * them is written as `light-dark()`, so the tokens follow the CSS color-scheme wherever they are
553
+ * used. `omit` leaves tokens out, such as ones a host supplies. */
497
554
  function themeStylesheet(selector, scheme, options = {}) {
498
- const { srgb, p3 } = generateTheme(scheme, options);
499
- const block = (vars, indent) => THEME_TOKENS.filter((token) => !options.omit?.includes(token) && vars[token] !== void 0).map((token) => `${indent}${token}: ${vars[token]};`).join("\n");
555
+ const tokens = THEME_TOKENS.filter((token) => !options.omit?.includes(token));
556
+ let srgb;
557
+ let p3;
558
+ if ("interface" in scheme) ({srgb, p3} = generateTheme(scheme, options));
559
+ else {
560
+ const light = generateTheme(scheme.light, options);
561
+ const dark = generateTheme(scheme.dark, options);
562
+ srgb = {};
563
+ p3 = {};
564
+ for (const token of tokens) {
565
+ srgb[token] = lightDark(light.srgb[token], dark.srgb[token]);
566
+ if (light.p3[token] !== void 0 || dark.p3[token] !== void 0) p3[token] = lightDark(light.p3[token] ?? light.srgb[token], dark.p3[token] ?? dark.srgb[token]);
567
+ }
568
+ }
569
+ const block = (vars, indent) => tokens.filter((token) => vars[token] !== void 0).map((token) => declaration(token, vars[token], indent)).join("\n");
500
570
  const wide = block(p3, " ");
501
571
  return `${selector} {\n${block(srgb, " ")}\n}\n${wide ? `\n@media (color-gamut: p3) {\n ${selector} {\n${wide}\n }\n}\n` : ""}`;
502
572
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@parallelworks/ui",
3
- "version": "0.53.0",
3
+ "version": "0.55.0",
4
4
  "description": "React UI components: a theme contract, icons, brand logos, primitives, lists, forms, a job graph, a code editor, a log viewer, a file explorer and an AI chat, each on its own subpath",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -60,6 +60,10 @@
60
60
  "types": "./dist/file-explorer/index.d.ts",
61
61
  "import": "./dist/file-explorer/index.js"
62
62
  },
63
+ "./access": {
64
+ "types": "./dist/access/index.d.ts",
65
+ "import": "./dist/access/index.js"
66
+ },
63
67
  "./ai": {
64
68
  "types": "./dist/ai/index.d.ts",
65
69
  "import": "./dist/ai/index.js"
@@ -98,7 +102,7 @@
98
102
  "clsx": "^2.1.1",
99
103
  "css-tree": "^3.2.1",
100
104
  "dequal": "^2.0.3",
101
- "katex": "^0.16.27",
105
+ "katex": "^0.19.0",
102
106
  "lucide-react": "1.52.0",
103
107
  "luxon": "^3.7.2",
104
108
  "react-zoom-pan-pinch": "^4.2.0",