@fibery/ui-kit 1.40.4 → 1.41.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 (141) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/eslint.config.mjs +16 -0
  3. package/package.json +8 -7
  4. package/src/a11y-color.test.ts +5 -24
  5. package/src/actions-menu/actions-menu-item.tsx +6 -9
  6. package/src/actions-menu/context-actions-menu.tsx +8 -3
  7. package/src/ai/model.tsx +0 -1
  8. package/src/ai/temperature.tsx +0 -1
  9. package/src/animated-height-container.tsx +3 -3
  10. package/src/antd/index.tsx +3 -0
  11. package/src/antd/input.tsx +0 -1
  12. package/src/antd/styles.ts +9 -9
  13. package/src/app-icon-with-fallback.tsx +5 -5
  14. package/src/app-icon-wrapper.tsx +2 -3
  15. package/src/app-icon.tsx +3 -3
  16. package/src/avatar.tsx +3 -3
  17. package/src/button/base-button.tsx +0 -1
  18. package/src/button/make-button-colors.ts +2 -2
  19. package/src/checkbox.tsx +1 -1
  20. package/src/collapsible-section.tsx +11 -1
  21. package/src/color-utils.test.ts +15 -25
  22. package/src/color-utils.ts +43 -8
  23. package/src/command-menu/index.tsx +1 -0
  24. package/src/context-menu/index.tsx +5 -5
  25. package/src/date-picker/contexts.ts +2 -2
  26. package/src/date-picker/date-range-picker.tsx +3 -4
  27. package/src/date-picker/single-date-picker.tsx +147 -119
  28. package/src/date-picker/types.ts +4 -3
  29. package/src/day-select/iso-week-day-select.tsx +2 -2
  30. package/src/day-select/week-day-select.tsx +2 -2
  31. package/src/delayed.tsx +0 -1
  32. package/src/design-system/alpha.test.ts +59 -0
  33. package/src/design-system/alpha.ts +41 -0
  34. package/src/design-system/animation.ts +10 -0
  35. package/src/design-system/colors-css.test.ts +39 -0
  36. package/src/design-system/colors-css.ts +25 -0
  37. package/src/design-system/colors-js.test.ts +232 -0
  38. package/src/design-system/colors-js.ts +107 -0
  39. package/src/design-system/colors.test.ts +74 -0
  40. package/src/{design-system.colors.ts → design-system/colors.ts} +133 -134
  41. package/src/design-system/date.ts +3 -0
  42. package/src/design-system/layout.ts +106 -0
  43. package/src/design-system/theme.test.ts +94 -0
  44. package/src/design-system/theme.ts +93 -0
  45. package/src/design-system/typography.ts +179 -0
  46. package/src/design-system/vars.test.ts +1679 -0
  47. package/src/design-system/vars.ts +52 -0
  48. package/src/design-system.test.ts +46 -303
  49. package/src/design-system.ts +25 -545
  50. package/src/dropdown-menu/index.tsx +5 -5
  51. package/src/emoji-picker/icon-emoji-picker.tsx +1 -1
  52. package/src/fibermoji-placeholder.tsx +3 -3
  53. package/src/field-container.tsx +11 -2
  54. package/src/file-item/file-icon.tsx +3 -3
  55. package/src/file-item-2.tsx +4 -10
  56. package/src/file-item.tsx +0 -1
  57. package/src/icons/ast/ChatBubble.ts +8 -0
  58. package/src/icons/ast/ChatFloat.ts +8 -0
  59. package/src/icons/ast/ChatSidebar.ts +8 -0
  60. package/src/icons/ast/FileOther.ts +8 -0
  61. package/src/icons/ast/NoBorder.ts +8 -0
  62. package/src/icons/ast/NoFill.ts +8 -0
  63. package/src/icons/ast/index.tsx +6 -0
  64. package/src/icons/react/ChatBubble.tsx +13 -0
  65. package/src/icons/react/ChatFloat.tsx +13 -0
  66. package/src/icons/react/ChatSidebar.tsx +13 -0
  67. package/src/icons/react/FileOther.tsx +13 -0
  68. package/src/icons/react/NoBorder.tsx +13 -0
  69. package/src/icons/react/NoFill.tsx +13 -0
  70. package/src/icons/react/index.tsx +6 -0
  71. package/src/icons/svg/chat-bubble.svg +4 -0
  72. package/src/icons/svg/chat-float.svg +4 -0
  73. package/src/icons/svg/chat-sidebar.svg +4 -0
  74. package/src/icons/svg/file-other.svg +3 -0
  75. package/src/icons/svg/no-border.svg +17 -0
  76. package/src/icons/svg/no-fill.svg +4 -0
  77. package/src/images-gallery/images-gallery.tsx +8 -6
  78. package/src/images-gallery/slide-buttons.tsx +2 -2
  79. package/src/is-iOS.ts +0 -1
  80. package/src/is-in-popup.ts +2 -1
  81. package/src/lists/actions-menu-row-surface.tsx +4 -4
  82. package/src/loading-sausage.tsx +2 -2
  83. package/src/media-query-utils.ts +1 -2
  84. package/src/mobile-keyboard-aware-popup.tsx +2 -2
  85. package/src/modal-menu/modal-menu-content.tsx +2 -2
  86. package/src/number-input/decimal.js +9 -7
  87. package/src/number-input/{number-inline-input-with-autosize.tsx → number-input-inline-with-autosize.tsx} +20 -41
  88. package/src/number-input/number-input-inline.tsx +118 -0
  89. package/src/number-input/{index.test.js → number-input.test.tsx} +38 -43
  90. package/src/number-input/number-input.tsx +63 -121
  91. package/src/number-input/types.ts +19 -0
  92. package/src/number-input/utils.ts +61 -0
  93. package/src/online-users.tsx +2 -2
  94. package/src/palette-generator.test.ts +24 -281
  95. package/src/palette-generator.ts +39 -45
  96. package/src/palettes/_.ts +72 -0
  97. package/src/palettes/slate-arch.colors-snapshot.test.ts +1689 -0
  98. package/src/palettes/slate-arch.ts +188 -0
  99. package/src/palettes/slate-user.colors-snapshot.test.ts +1689 -0
  100. package/src/palettes/slate-user.ts +187 -0
  101. package/src/palettes/warm-arch.colors-snapshot.test.ts +1689 -0
  102. package/src/palettes/warm-arch.ts +222 -0
  103. package/src/palettes/warm-user.colors-snapshot.test.ts +1689 -0
  104. package/src/palettes/warm-user.ts +222 -0
  105. package/src/popover/get-element-ref.ts +28 -0
  106. package/src/popover/index.tsx +232 -333
  107. package/src/popover/{mobile-popup-context.tsx → mobile-popover-context.tsx} +7 -7
  108. package/src/popover/mobile-popover.tsx +169 -0
  109. package/src/popover/modifiers.tsx +2 -2
  110. package/src/popover/popup-stack-context.tsx +8 -9
  111. package/src/root-theme-provider.test.tsx +114 -19
  112. package/src/scale-generator.ts +31 -22
  113. package/src/select/components/menu-list-virtualized.tsx +5 -3
  114. package/src/select/index.tsx +6 -5
  115. package/src/select/select.tsx +36 -38
  116. package/src/select/util.ts +1 -1
  117. package/src/static-palettes.ts +221 -11
  118. package/src/thematic-controls.tsx +6 -6
  119. package/src/thematic-scales.tsx +15 -15
  120. package/src/thematic-state.ts +57 -20
  121. package/src/thematic.tsx +36 -32
  122. package/src/theme-provider.test.tsx +31 -19
  123. package/src/theme-provider.tsx +41 -38
  124. package/src/theme-settings.ts +66 -11
  125. package/src/theme-styles.ts +53 -8
  126. package/src/toast/toast.tsx +1 -2
  127. package/src/toggle.tsx +2 -2
  128. package/src/tooltip.tsx +4 -3
  129. package/src/type-badge.tsx +4 -11
  130. package/src/unit/styles.ts +0 -23
  131. package/src/use-is-phone.tsx +7 -2
  132. package/src/use-on-screen-keyboard-data.tsx +2 -2
  133. package/src/with-data.tsx +4 -3
  134. package/src/workflow-progress-icon.tsx +2 -2
  135. package/.eslintignore +0 -3
  136. package/.eslintrc +0 -14
  137. package/src/__mocks__/createInlineTheme.js +0 -3
  138. package/src/__snapshots__/design-system.test.ts.snap +0 -7265
  139. package/src/create-inline-theme.ts +0 -67
  140. package/src/number-input/index.js +0 -191
  141. package/src/palette.ts +0 -253
@@ -1,6 +1,6 @@
1
- /* eslint-disable max-lines */
2
- import {getAlpha, OKLCH, parse, to, toOKLCH} from "./color-utils";
1
+ import {getAlpha, OKLCH, parse, to} from "./color-utils";
3
2
  import {type ColorScale, makeDefaultPalette, makeThematicPalette} from "./palette-generator";
3
+ import {zeroBasedFromOneBased} from "./scale-generator";
4
4
 
5
5
  function roundToThreeDigits(number: number) {
6
6
  return Math.round(number * 1000) / 1000;
@@ -16,11 +16,11 @@ function getOklch(color: string): {l: number; c: number; h: number} {
16
16
  }
17
17
 
18
18
  function extractLightness(scale: ColorScale): number[] {
19
- return scale.slice(1).map((color) => getOklch(color).l);
19
+ return zeroBasedFromOneBased(scale).map((color) => getOklch(color).l);
20
20
  }
21
21
 
22
22
  function extractChromaNormalized(scale: ColorScale): number[] {
23
- const chromas = scale.slice(1).map((color) => getOklch(color).c);
23
+ const chromas = zeroBasedFromOneBased(scale).map((color) => getOklch(color).c);
24
24
  const maxChroma = Math.max(...chromas);
25
25
  return chromas.map((c) => roundToThreeDigits(c / maxChroma));
26
26
  }
@@ -202,81 +202,6 @@ describe("palette-generator", () => {
202
202
  });
203
203
  });
204
204
 
205
- describe("makeDefaultPalette", () => {
206
- it("snapshots default palette in OKLCH", () => {
207
- const palette = makeDefaultPalette();
208
- expect({
209
- base: palette.base.map(toOKLCH),
210
- baseDark: palette.baseDark.map(toOKLCH),
211
- accent: palette.accent.map(toOKLCH),
212
- accentDark: palette.accentDark.map(toOKLCH),
213
- }).toMatchInlineSnapshot(`
214
- {
215
- "accent": [
216
- "oklch(100% 0 none)",
217
- "oklch(99.069% 0.00291 264.54)",
218
- "oklch(98.983% 0.00437 264.54)",
219
- "oklch(96.966% 0.01293 264.51)",
220
- "oklch(95.012% 0.02046 264.47)",
221
- "oklch(92.145% 0.03068 264.41)",
222
- "oklch(88.367% 0.04361 264.32)",
223
- "oklch(82.757% 0.06206 264.15)",
224
- "oklch(76.14% 0.08554 263.86)",
225
- "oklch(58.48% 0.15116 262.64)",
226
- "oklch(54.173% 0.16179 262.38)",
227
- "oklch(49.642% 0.14201 262.46)",
228
- "oklch(26.071% 0.07125 262.54)",
229
- ],
230
- "accentDark": [
231
- "oklch(100% 0 none)",
232
- "oklch(20.512% 0.01807 266.69)",
233
- "oklch(22.974% 0.03429 266.01)",
234
- "oklch(27.284% 0.05415 265.42)",
235
- "oklch(29.742% 0.06735 265.08)",
236
- "oklch(32.452% 0.07215 265.13)",
237
- "oklch(35.981% 0.07843 265.18)",
238
- "oklch(41.256% 0.10936 264.62)",
239
- "oklch(47.972% 0.14454 264.22)",
240
- "oklch(57.658% 0.15178 264.65)",
241
- "oklch(62.928% 0.13984 265.13)",
242
- "oklch(76.225% 0.09124 266.35)",
243
- "oklch(95.899% 0.01681 267.31)",
244
- ],
245
- "base": [
246
- "oklch(100% 0 none)",
247
- "oklch(99.241% 0 none)",
248
- "oklch(97.719% 0 none)",
249
- "oklch(96.955% 0 none)",
250
- "oklch(94.656% 0 none)",
251
- "oklch(93.115% 0 none)",
252
- "oklch(91.568% 0 none)",
253
- "oklch(89.235% 0 none)",
254
- "oklch(82.937% 0 none)",
255
- "oklch(69.959% 0 none)",
256
- "oklch(57.217% 0 none)",
257
- "oklch(48.318% 0 none)",
258
- "oklch(20.441% 0 none)",
259
- ],
260
- "baseDark": [
261
- "oklch(15.789% 0 none)",
262
- "oklch(20.441% 0 none)",
263
- "oklch(22.667% 0 none)",
264
- "oklch(25.908% 0 none)",
265
- "oklch(28.012% 0 none)",
266
- "oklch(30.078% 0 none)",
267
- "oklch(32.109% 0 none)",
268
- "oklch(36.079% 0 none)",
269
- "oklch(43.714% 0 none)",
270
- "oklch(54.586% 0 none)",
271
- "oklch(59.818% 0 none)",
272
- "oklch(70.787% 0 none)",
273
- "oklch(94.656% 0 none)",
274
- ],
275
- }
276
- `);
277
- });
278
- });
279
-
280
205
  describe("white/black scales", () => {
281
206
  it("generated neutral scales match default palette", () => {
282
207
  const defaultPalette = makeDefaultPalette();
@@ -287,9 +212,8 @@ describe("palette-generator", () => {
287
212
  accentChroma: 0.16,
288
213
  });
289
214
 
290
- expect(generated.white).toMatchInlineSnapshot(`
215
+ expect(zeroBasedFromOneBased(generated.whiteA)).toMatchInlineSnapshot(`
291
216
  [
292
- "rgb(255,255,255)",
293
217
  "rgba(255,255,255,0)",
294
218
  "rgba(255,255,255,0.01)",
295
219
  "rgba(255,255,255,0.03)",
@@ -304,9 +228,8 @@ describe("palette-generator", () => {
304
228
  "rgba(255,255,255,0.92)",
305
229
  ]
306
230
  `);
307
- expect(generated.black).toMatchInlineSnapshot(`
231
+ expect(zeroBasedFromOneBased(generated.blackA)).toMatchInlineSnapshot(`
308
232
  [
309
- "rgb(0,0,0)",
310
233
  "rgba(0,0,0,0.01)",
311
234
  "rgba(0,0,0,0.03)",
312
235
  "rgba(0,0,0,0.05)",
@@ -322,216 +245,36 @@ describe("palette-generator", () => {
322
245
  ]
323
246
  `);
324
247
 
248
+ const whiteADefault = zeroBasedFromOneBased(defaultPalette.whiteA);
249
+ const blackADefault = zeroBasedFromOneBased(defaultPalette.blackA);
250
+ const whiteAGenerated = zeroBasedFromOneBased(generated.whiteA);
251
+ const blackAGenerated = zeroBasedFromOneBased(generated.blackA);
325
252
  // default palette uses hsla strings, generated uses rgba — compare parsed alpha values
326
- for (let i = 0; i < 13; i++) {
327
- const defWhiteAlpha = getAlpha(defaultPalette.white[i]);
328
- const genWhiteAlpha = getAlpha(generated.white[i]);
253
+ for (let i = 0; i < 12; i++) {
254
+ const defWhiteAlpha = getAlpha(whiteADefault[i]);
255
+ const genWhiteAlpha = getAlpha(whiteAGenerated[i]);
329
256
  expect(genWhiteAlpha).toBeCloseTo(defWhiteAlpha, 2);
330
257
 
331
- const defBlackAlpha = getAlpha(defaultPalette.black[i]);
332
- const genBlackAlpha = getAlpha(generated.black[i]);
258
+ const defBlackAlpha = getAlpha(blackADefault[i]);
259
+ const genBlackAlpha = getAlpha(blackAGenerated[i]);
333
260
  expect(genBlackAlpha).toBeCloseTo(defBlackAlpha, 2);
334
261
  }
335
262
  });
336
263
  });
337
264
 
338
265
  describe("white/black tinting across hues", () => {
339
- it("white[0] should be tinted for all hues when chroma > 0", () => {
266
+ it("white/black should be tinted for all hues when chroma > 0", () => {
340
267
  const hues = Array.from({length: 36}, (_, i) => i * 10);
341
- const results = hues.map((hue) => {
342
- const palette = makeThematicPalette({baseHue: hue, baseChroma: 0.175, accentHue: hue, accentChroma: 0.16});
343
- return {hue, white0: palette.white[0], black0: palette.black[0]};
344
- });
345
268
 
346
- // Every hue should produce a tinted white (not pure #fff)
347
- for (const {hue, white0} of results) {
348
- expect({hue, white0}).not.toEqual({hue, white0: "rgb(255,255,255)"});
269
+ for (const hue of hues) {
270
+ const palette = makeThematicPalette({baseHue: hue, baseChroma: 0.175, accentHue: hue, accentChroma: 0.16});
271
+ // white should not be pure white
272
+ expect(palette.white).not.toBe("rgb(255,255,255)");
273
+ expect(palette.white).not.toBe("#FFFFFF");
274
+ // black should not be pure black
275
+ expect(palette.black).not.toBe("rgb(0,0,0)");
276
+ expect(palette.black).not.toBe("#000000");
349
277
  }
350
-
351
- expect(results).toMatchInlineSnapshot(`
352
- [
353
- {
354
- "black0": "rgb(3,0,1)",
355
- "hue": 0,
356
- "white0": "rgb(255,245,249)",
357
- },
358
- {
359
- "black0": "rgb(3,0,1)",
360
- "hue": 10,
361
- "white0": "rgb(255,245,246)",
362
- },
363
- {
364
- "black0": "rgb(3,0,1)",
365
- "hue": 20,
366
- "white0": "rgb(255,245,244)",
367
- },
368
- {
369
- "black0": "rgb(3,0,0)",
370
- "hue": 30,
371
- "white0": "rgb(255,245,242)",
372
- },
373
- {
374
- "black0": "rgb(3,1,0)",
375
- "hue": 40,
376
- "white0": "rgb(255,246,241)",
377
- },
378
- {
379
- "black0": "rgb(3,1,0)",
380
- "hue": 50,
381
- "white0": "rgb(255,246,239)",
382
- },
383
- {
384
- "black0": "rgb(3,1,0)",
385
- "hue": 60,
386
- "white0": "rgb(255,247,238)",
387
- },
388
- {
389
- "black0": "rgb(2,1,0)",
390
- "hue": 70,
391
- "white0": "rgb(255,248,237)",
392
- },
393
- {
394
- "black0": "rgb(2,1,0)",
395
- "hue": 80,
396
- "white0": "rgb(255,248,236)",
397
- },
398
- {
399
- "black0": "rgb(2,1,0)",
400
- "hue": 90,
401
- "white0": "rgb(254,249,236)",
402
- },
403
- {
404
- "black0": "rgb(2,1,0)",
405
- "hue": 100,
406
- "white0": "rgb(252,250,237)",
407
- },
408
- {
409
- "black0": "rgb(1,1,0)",
410
- "hue": 110,
411
- "white0": "rgb(250,251,237)",
412
- },
413
- {
414
- "black0": "rgb(1,1,0)",
415
- "hue": 120,
416
- "white0": "rgb(247,251,238)",
417
- },
418
- {
419
- "black0": "rgb(1,1,0)",
420
- "hue": 130,
421
- "white0": "rgb(245,252,240)",
422
- },
423
- {
424
- "black0": "rgb(0,2,0)",
425
- "hue": 140,
426
- "white0": "rgb(243,252,241)",
427
- },
428
- {
429
- "black0": "rgb(0,2,0)",
430
- "hue": 150,
431
- "white0": "rgb(241,253,243)",
432
- },
433
- {
434
- "black0": "rgb(0,2,1)",
435
- "hue": 160,
436
- "white0": "rgb(240,253,245)",
437
- },
438
- {
439
- "black0": "rgb(0,2,1)",
440
- "hue": 170,
441
- "white0": "rgb(238,253,247)",
442
- },
443
- {
444
- "black0": "rgb(0,2,1)",
445
- "hue": 180,
446
- "white0": "rgb(237,253,250)",
447
- },
448
- {
449
- "black0": "rgb(0,2,2)",
450
- "hue": 190,
451
- "white0": "rgb(237,253,252)",
452
- },
453
- {
454
- "black0": "rgb(0,2,2)",
455
- "hue": 200,
456
- "white0": "rgb(236,253,254)",
457
- },
458
- {
459
- "black0": "rgb(0,2,2)",
460
- "hue": 210,
461
- "white0": "rgb(237,253,255)",
462
- },
463
- {
464
- "black0": "rgb(0,2,3)",
465
- "hue": 220,
466
- "white0": "rgb(237,252,255)",
467
- },
468
- {
469
- "black0": "rgb(0,1,3)",
470
- "hue": 230,
471
- "white0": "rgb(238,252,255)",
472
- },
473
- {
474
- "black0": "rgb(0,1,3)",
475
- "hue": 240,
476
- "white0": "rgb(239,251,255)",
477
- },
478
- {
479
- "black0": "rgb(0,1,3)",
480
- "hue": 250,
481
- "white0": "rgb(241,251,255)",
482
- },
483
- {
484
- "black0": "rgb(0,1,4)",
485
- "hue": 260,
486
- "white0": "rgb(243,250,255)",
487
- },
488
- {
489
- "black0": "rgb(1,1,4)",
490
- "hue": 270,
491
- "white0": "rgb(244,249,255)",
492
- },
493
- {
494
- "black0": "rgb(1,1,4)",
495
- "hue": 280,
496
- "white0": "rgb(247,248,255)",
497
- },
498
- {
499
- "black0": "rgb(1,1,3)",
500
- "hue": 290,
501
- "white0": "rgb(249,248,255)",
502
- },
503
- {
504
- "black0": "rgb(1,1,3)",
505
- "hue": 300,
506
- "white0": "rgb(251,247,255)",
507
- },
508
- {
509
- "black0": "rgb(2,1,3)",
510
- "hue": 310,
511
- "white0": "rgb(253,246,255)",
512
- },
513
- {
514
- "black0": "rgb(2,1,2)",
515
- "hue": 320,
516
- "white0": "rgb(255,246,255)",
517
- },
518
- {
519
- "black0": "rgb(2,1,2)",
520
- "hue": 330,
521
- "white0": "rgb(255,245,255)",
522
- },
523
- {
524
- "black0": "rgb(3,1,2)",
525
- "hue": 340,
526
- "white0": "rgb(255,245,253)",
527
- },
528
- {
529
- "black0": "rgb(3,0,1)",
530
- "hue": 350,
531
- "white0": "rgb(255,245,251)",
532
- },
533
- ]
534
- `);
535
278
  });
536
279
  });
537
280
 
@@ -1,42 +1,34 @@
1
+ import {slateUserPalette} from "./palettes/slate-user";
2
+ import {slateArchPalette} from "./palettes/slate-arch";
3
+ import {warmUserPalette} from "./palettes/warm-user";
4
+ import {warmArchPalette} from "./palettes/warm-arch";
1
5
  import {
2
- blackAScale,
3
- indigoDarkScale,
4
- indigoScale,
5
- redDarkScale,
6
- redScale,
7
- slateDarkScale,
8
- slateScale,
9
- tealDarkScale,
10
- tealScale,
11
- whiteAScale,
12
- yellowDarkScale,
13
- yellowScale,
14
- } from "./palette";
15
- import {
16
- BasedScale12,
17
6
  DEFAULT_DARK_CURVES,
18
7
  DEFAULT_LIGHT_CURVES,
19
- generateBlackScale,
8
+ generateBlacks,
20
9
  generateColorScale,
21
10
  generateGrayScale,
22
11
  generateInterpolatedScale,
23
12
  generatePresetScale,
24
- generateWhiteScale,
13
+ generateWhites,
25
14
  type InterpolatedScaleConfig,
26
- type Scale12,
15
+ OneBasedScale,
27
16
  paletteFromHue,
28
17
  paletteFromHueBoth,
29
18
  SCALE_PRESETS,
30
19
  type ScaleConfig,
31
20
  type ScaleCurves,
21
+ type ZeroBasedScale,
32
22
  } from "./scale-generator";
33
23
 
34
- export type ColorScale = BasedScale12<string>;
24
+ export type ColorScale = OneBasedScale<string>;
35
25
 
36
26
  export interface ThemePalette {
37
27
  key: string;
38
- white: ColorScale;
39
- black: ColorScale;
28
+ white: string;
29
+ black: string;
30
+ whiteA: ColorScale;
31
+ blackA: ColorScale;
40
32
  base: ColorScale;
41
33
  baseDark: ColorScale;
42
34
  accent: ColorScale;
@@ -49,23 +41,24 @@ export interface ThemePalette {
49
41
  yellowDark: ColorScale;
50
42
  }
51
43
 
52
- export const defaultPaletteKey = "default";
44
+ export const defaultPaletteKey = slateUserPalette.key;
45
+
53
46
  export function makeDefaultPalette(): ThemePalette {
54
- return {
55
- key: defaultPaletteKey,
56
- white: whiteAScale,
57
- black: blackAScale,
58
- base: slateScale,
59
- baseDark: slateDarkScale,
60
- accent: indigoScale,
61
- accentDark: indigoDarkScale,
62
- red: redScale,
63
- redDark: redDarkScale,
64
- teal: tealScale,
65
- tealDark: tealDarkScale,
66
- yellow: yellowScale,
67
- yellowDark: yellowDarkScale,
68
- };
47
+ return slateUserPalette;
48
+ }
49
+
50
+ export function selectPalette({
51
+ warmLook = false,
52
+ isArchitect = false,
53
+ }: {
54
+ warmLook?: boolean;
55
+ isArchitect?: boolean;
56
+ } = {}): ThemePalette {
57
+ if (warmLook) {
58
+ return isArchitect ? warmArchPalette : warmUserPalette;
59
+ } else {
60
+ return isArchitect ? slateArchPalette : slateUserPalette;
61
+ }
69
62
  }
70
63
 
71
64
  export type ThematicPrefs = {
@@ -93,13 +86,12 @@ function shiftHueTowards(hue: number, targetHue: number, amount: number): number
93
86
 
94
87
  export function makeThematicPalette(config: ThematicPrefs): ThemePalette {
95
88
  const {baseHue = 0, baseChroma = 0, accentHue, accentChroma, contrast} = config;
96
-
97
- const white = generateWhiteScale(baseHue, baseChroma, config.whiteLuminosity, config.whiteChroma);
98
- const black = generateBlackScale(baseHue, baseChroma, config.blackLuminosity, config.blackChroma);
89
+ const {white, whiteA} = generateWhites(baseHue, baseChroma, config.whiteLuminosity, config.whiteChroma);
90
+ const {black, blackA} = generateBlacks(baseHue, baseChroma, config.blackLuminosity, config.blackChroma);
99
91
 
100
92
  // Generate base/gray scales with tinted base colors
101
- const base = generateGrayScale({hue: baseHue, chroma: baseChroma, mode: "light", contrast, base: white[0]});
102
- const baseDark = generateGrayScale({hue: baseHue, chroma: baseChroma, mode: "dark", contrast, base: black[0]});
93
+ const base = generateGrayScale({hue: baseHue, chroma: baseChroma, mode: "light", contrast});
94
+ const baseDark = generateGrayScale({hue: baseHue, chroma: baseChroma, mode: "dark", contrast});
103
95
 
104
96
  // Generate accent scales
105
97
  const accent = generateColorScale({hue: accentHue, chroma: accentChroma, mode: "light", contrast});
@@ -134,6 +126,8 @@ export function makeThematicPalette(config: ThematicPrefs): ThemePalette {
134
126
  key: JSON.stringify(config),
135
127
  white,
136
128
  black,
129
+ whiteA,
130
+ blackA,
137
131
  base,
138
132
  baseDark,
139
133
  accent,
@@ -148,18 +142,18 @@ export function makeThematicPalette(config: ThematicPrefs): ThemePalette {
148
142
  }
149
143
 
150
144
  export {
151
- generateBlackScale,
145
+ generateBlacks,
152
146
  generateColorScale,
153
147
  generateGrayScale,
154
148
  generateInterpolatedScale,
155
149
  generatePresetScale,
156
- generateWhiteScale,
150
+ generateWhites,
157
151
  paletteFromHue,
158
152
  paletteFromHueBoth,
159
153
  SCALE_PRESETS,
160
154
  DEFAULT_LIGHT_CURVES,
161
155
  DEFAULT_DARK_CURVES,
162
- type Scale12,
156
+ type ZeroBasedScale,
163
157
  type ScaleConfig,
164
158
  type ScaleCurves,
165
159
  type InterpolatedScaleConfig,
@@ -0,0 +1,72 @@
1
+ import {makeThemeDefs} from "../design-system/colors";
2
+ import {HSL, isValidColor, OKLCH, produceColor, sRGB} from "../color-utils";
3
+ import {ThemePalette} from "../palette-generator";
4
+
5
+ function verboseColor(color: string) {
6
+ return `${produceColor(color, [], sRGB)} / ${produceColor(color, [], OKLCH)} / ${produceColor(color, [], HSL)}`;
7
+ }
8
+
9
+ const COLOR_PREFIXES = ["rgba(", "rgb(", "hsla(", "hsl("] as const;
10
+ const HEX_CHARS = "0123456789abcdefABCDEF";
11
+
12
+ function replaceColorsInString(str: string) {
13
+ let result = "";
14
+ let i = 0;
15
+ const seen = new Set<string>();
16
+ while (i < str.length) {
17
+ const position = i;
18
+ const prefix = COLOR_PREFIXES.find((p) => str.startsWith(p, position));
19
+ if (prefix) {
20
+ const closeIdx = str.indexOf(")", i + prefix.length);
21
+ if (closeIdx !== -1) {
22
+ const candidate = str.slice(i, closeIdx + 1);
23
+ if (isValidColor(candidate)) {
24
+ const verbose = verboseColor(candidate);
25
+ result += seen.has(verbose) ? "[SAME]" : verbose;
26
+ seen.add(verbose);
27
+ i = closeIdx + 1;
28
+ continue;
29
+ }
30
+ }
31
+ }
32
+ if (str[i] === "#") {
33
+ let end = i + 1;
34
+ while (end < str.length && HEX_CHARS.includes(str[end])) {
35
+ end++;
36
+ }
37
+ const candidate = str.slice(i, end);
38
+ if (candidate.length >= 4 && isValidColor(candidate)) {
39
+ const verbose = verboseColor(candidate);
40
+ result += seen.has(verbose) ? "[SAME]" : verbose;
41
+ seen.add(verbose);
42
+ i = end;
43
+ continue;
44
+ }
45
+ }
46
+ result += str[i];
47
+ i++;
48
+ }
49
+ return result;
50
+ }
51
+
52
+ function deepMapColors(value: unknown): unknown {
53
+ if (typeof value === "string") {
54
+ if (isValidColor(value)) {
55
+ return verboseColor(value);
56
+ }
57
+ return replaceColorsInString(value);
58
+ }
59
+ if (Array.isArray(value)) {
60
+ return value.map(deepMapColors);
61
+ }
62
+ if (typeof value === "object" && value !== null) {
63
+ return Object.fromEntries(Object.entries(value).map(([k, v]) => [k, deepMapColors(v)]));
64
+ }
65
+ return value;
66
+ }
67
+
68
+ export function colors(palette: ThemePalette) {
69
+ const {colors} = makeThemeDefs(palette);
70
+
71
+ return deepMapColors(colors);
72
+ }