@charcoal-ui/styled 2.4.0 → 2.6.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 (67) hide show
  1. package/dist/SetThemeScript.d.ts +20 -20
  2. package/dist/TokenInjector.d.ts +12 -12
  3. package/dist/TokenInjector.d.ts.map +1 -1
  4. package/dist/builders/border.d.ts +10 -0
  5. package/dist/builders/border.d.ts.map +1 -0
  6. package/dist/builders/borderRadius.d.ts +7 -0
  7. package/dist/builders/borderRadius.d.ts.map +1 -0
  8. package/dist/builders/colors.d.ts +13 -0
  9. package/dist/builders/colors.d.ts.map +1 -0
  10. package/dist/builders/elementEffect.d.ts +7 -0
  11. package/dist/builders/elementEffect.d.ts.map +1 -0
  12. package/dist/builders/o.d.ts +114 -0
  13. package/dist/builders/o.d.ts.map +1 -0
  14. package/dist/builders/outline.d.ts +10 -0
  15. package/dist/builders/outline.d.ts.map +1 -0
  16. package/dist/builders/size.d.ts +23 -0
  17. package/dist/builders/size.d.ts.map +1 -0
  18. package/dist/builders/spacing.d.ts +15 -0
  19. package/dist/builders/spacing.d.ts.map +1 -0
  20. package/dist/builders/transition.d.ts +7 -0
  21. package/dist/builders/transition.d.ts.map +1 -0
  22. package/dist/builders/typography.d.ts +11 -0
  23. package/dist/builders/typography.d.ts.map +1 -0
  24. package/dist/defineThemeVariables.test.d.ts +1 -1
  25. package/dist/{lib.d.ts → factories/lib.d.ts} +88 -89
  26. package/dist/factories/lib.d.ts.map +1 -0
  27. package/dist/helper.d.ts +38 -38
  28. package/dist/helper.d.ts.map +1 -1
  29. package/dist/index.cjs.js +918 -0
  30. package/dist/index.cjs.js.map +1 -0
  31. package/dist/index.d.ts +128 -67
  32. package/dist/index.d.ts.map +1 -1
  33. package/dist/index.esm.js +886 -0
  34. package/dist/index.esm.js.map +1 -0
  35. package/dist/index.story.d.ts +25 -24
  36. package/dist/index.story.d.ts.map +1 -1
  37. package/dist/index.test.d.ts +2 -0
  38. package/dist/index.test.d.ts.map +1 -0
  39. package/dist/internals/index.d.ts +42 -0
  40. package/dist/internals/index.d.ts.map +1 -0
  41. package/dist/util.d.ts +100 -66
  42. package/dist/util.d.ts.map +1 -1
  43. package/package.json +19 -16
  44. package/src/__snapshots__/index.test.tsx.snap +768 -0
  45. package/src/builders/border.ts +63 -0
  46. package/src/builders/borderRadius.ts +32 -0
  47. package/src/builders/colors.ts +198 -0
  48. package/src/builders/elementEffect.ts +54 -0
  49. package/src/builders/o.ts +36 -0
  50. package/src/builders/outline.ts +79 -0
  51. package/src/builders/size.ts +61 -0
  52. package/src/builders/spacing.ts +113 -0
  53. package/src/builders/transition.ts +32 -0
  54. package/src/builders/typography.ts +97 -0
  55. package/src/{lib.ts → factories/lib.ts} +30 -25
  56. package/src/index.story.tsx +2 -2
  57. package/src/index.test.tsx +24 -0
  58. package/src/index.ts +36 -696
  59. package/src/internals/index.ts +84 -0
  60. package/src/util.ts +46 -3
  61. package/dist/index.cjs +0 -1051
  62. package/dist/index.cjs.map +0 -1
  63. package/dist/index.modern.js +0 -826
  64. package/dist/index.modern.js.map +0 -1
  65. package/dist/index.module.js +0 -1034
  66. package/dist/index.module.js.map +0 -1
  67. package/dist/lib.d.ts.map +0 -1
@@ -0,0 +1,886 @@
1
+ // src/util.ts
2
+ import {
3
+ applyEffect,
4
+ customPropertyToken,
5
+ disabledSelector,
6
+ filterObject,
7
+ flatMapObject,
8
+ notDisabledSelector
9
+ } from "@charcoal-ui/utils";
10
+ function unreachable(value) {
11
+ throw new Error(
12
+ arguments.length === 0 ? "unreachable" : `unreachable (${JSON.stringify(value)})`
13
+ );
14
+ }
15
+ var isPresent = (value) => value != null;
16
+ function objectAssign(...sources) {
17
+ return Object.assign({}, ...sources);
18
+ }
19
+ function keyof(obj) {
20
+ return Object.keys(obj);
21
+ }
22
+ function wrapArray(value) {
23
+ return Array.isArray(value) ? value : [value];
24
+ }
25
+ var noThemeProvider = new Error(
26
+ "`theme` is invalid. `<ThemeProvider>` is not likely mounted."
27
+ );
28
+ function defineThemeVariables(colorParams, effectParams) {
29
+ return function toCssObject(props) {
30
+ if (!isPresent(props.theme)) {
31
+ throw noThemeProvider;
32
+ }
33
+ const colors2 = filterObject(colorParams, isPresent);
34
+ const effects = Object.entries({
35
+ ...props.theme.effect,
36
+ ...effectParams
37
+ });
38
+ return flatMapObject(colors2, (colorKey, color) => [
39
+ [customPropertyToken(colorKey), color],
40
+ ...effects.map(([effectKey, effect]) => [
41
+ customPropertyToken(colorKey, [effectKey]),
42
+ applyEffect(color, [effect])
43
+ ])
44
+ ]);
45
+ };
46
+ }
47
+ function isSupportedEffect(effect) {
48
+ return ["hover", "press", "disabled"].includes(effect);
49
+ }
50
+ var variable = (value) => `var(${value})`;
51
+ function onEffectPseudo(effect, css2) {
52
+ return effect === "hover" ? { "&:hover": { [notDisabledSelector]: css2 } } : effect === "press" ? { "&:active": { [notDisabledSelector]: css2 } } : effect === "disabled" ? { [disabledSelector]: css2 } : unreachable(effect);
53
+ }
54
+
55
+ // src/internals/index.ts
56
+ var internalSym = Symbol("internal");
57
+ function createInternal({
58
+ toCSS,
59
+ context = {}
60
+ }) {
61
+ return {
62
+ [internalSym]: {
63
+ toCSS,
64
+ context
65
+ }
66
+ };
67
+ }
68
+ function __DO_NOT_USE_ACCESS_PRIVATE_PROPERTY__(internal) {
69
+ return internal[internalSym];
70
+ }
71
+ var shouldCancelHalfLeading = ({
72
+ cancelHalfLeadingPx,
73
+ hasVerticalPadding = false
74
+ }) => cancelHalfLeadingPx !== void 0 && !hasVerticalPadding;
75
+ function getContext(internals) {
76
+ return internals.reduce(
77
+ (context, internal) => ({
78
+ ...context,
79
+ ...__DO_NOT_USE_ACCESS_PRIVATE_PROPERTY__(internal).context
80
+ }),
81
+ {}
82
+ );
83
+ }
84
+ function toCSSObjects(internals) {
85
+ const context = getContext(internals);
86
+ return internals.map(
87
+ (v) => __DO_NOT_USE_ACCESS_PRIVATE_PROPERTY__(v).toCSS(context)
88
+ );
89
+ }
90
+
91
+ // src/factories/lib.ts
92
+ var defineProperties = (source, member, chain) => Object.defineProperties(
93
+ source,
94
+ Object.fromEntries(
95
+ member.map((key) => [
96
+ key,
97
+ { get: () => chain(key), enumerable: true, configurable: true }
98
+ ])
99
+ )
100
+ );
101
+ var defineMethods = (source, member, chain) => Object.defineProperties(
102
+ source,
103
+ Object.fromEntries(
104
+ member.map((key) => [
105
+ key,
106
+ {
107
+ value: (...args) => chain(key, ...args),
108
+ enumerable: true,
109
+ configurable: true
110
+ }
111
+ ])
112
+ )
113
+ );
114
+ var defineConstantProperties = (source, def) => defineProperties(source, Object.keys(def), (key) => def[key]);
115
+ var definePropertyChains = (modifiers, source) => function definePropertiesRecursively(applied) {
116
+ const notApplied = modifiers.filter((v) => !applied.includes(v));
117
+ return defineProperties(
118
+ source(applied),
119
+ notApplied,
120
+ (modifier) => notApplied.length === 0 ? unreachable() : definePropertiesRecursively([...applied, modifier])
121
+ );
122
+ }([]);
123
+ var defineMethodChains = (modifiers, source, ..._inferPhantom) => function defineMethodsRecursively(applied) {
124
+ const notApplied = modifiers.filter(
125
+ (v) => !applied.map(([w]) => w).includes(v)
126
+ );
127
+ return defineMethods(
128
+ source(applied),
129
+ notApplied,
130
+ (modifier, ...args) => notApplied.length === 0 ? unreachable() : defineMethodsRecursively([...applied, [modifier, ...args]])
131
+ );
132
+ }([]);
133
+
134
+ // src/builders/border.ts
135
+ var borderDirections = ["top", "right", "bottom", "left"];
136
+ function borderProperty(direction) {
137
+ return `border-${direction}`;
138
+ }
139
+ function borderShorthand(color) {
140
+ return `solid 1px ${color}`;
141
+ }
142
+ var createBorderCss = (theme) => (variant, directions) => {
143
+ const all = directions.length === 0;
144
+ const value = borderShorthand(theme.border[variant].color);
145
+ return createInternal({
146
+ toCSS() {
147
+ return {
148
+ ...all ? { border: value } : directions.reduce(
149
+ (acc, direction) => ({
150
+ ...acc,
151
+ [borderProperty(direction)]: value
152
+ }),
153
+ {}
154
+ )
155
+ };
156
+ }
157
+ });
158
+ };
159
+ function border(theme) {
160
+ const borderTypes = keyof(theme.border);
161
+ const borderCss = createBorderCss(theme);
162
+ const borderObject = defineConstantProperties(
163
+ {},
164
+ {
165
+ border: defineProperties(
166
+ {},
167
+ borderTypes,
168
+ (variant) => definePropertyChains(
169
+ borderDirections,
170
+ (modifiers) => borderCss(variant, modifiers)
171
+ )
172
+ )
173
+ }
174
+ );
175
+ return borderObject;
176
+ }
177
+
178
+ // src/builders/borderRadius.ts
179
+ import { px } from "@charcoal-ui/utils";
180
+ var createBorderRadiusCss = (theme) => (size2) => {
181
+ return createInternal({
182
+ toCSS() {
183
+ return {
184
+ borderRadius: px(theme.borderRadius[size2])
185
+ };
186
+ }
187
+ });
188
+ };
189
+ function borderRadius(theme) {
190
+ const borderRadiusCss = createBorderRadiusCss(theme);
191
+ const borderRadiusObject = defineConstantProperties(
192
+ {},
193
+ {
194
+ borderRadius: (radius) => borderRadiusCss(radius)
195
+ }
196
+ );
197
+ return borderRadiusObject;
198
+ }
199
+
200
+ // src/builders/colors.ts
201
+ import {
202
+ applyEffect as applyEffect2,
203
+ applyEffectToGradient,
204
+ customPropertyToken as customPropertyToken2,
205
+ dur as dur2,
206
+ gradient
207
+ } from "@charcoal-ui/utils";
208
+ import warning from "warning";
209
+
210
+ // src/builders/transition.ts
211
+ import { dur } from "@charcoal-ui/utils";
212
+ var TRANSITION_DURATION = 0.2;
213
+ function transition(_theme) {
214
+ const duration = dur(TRANSITION_DURATION);
215
+ const transition2 = (property) => ({
216
+ transition: property.map((v) => `${duration} ${v}`).join(", ")
217
+ });
218
+ function toCSS({
219
+ colorTransition = false,
220
+ backgroundColorTransition = false,
221
+ boxShadowTransition = false
222
+ }) {
223
+ return transition2(
224
+ [
225
+ colorTransition ? "color" : null,
226
+ backgroundColorTransition ? "background-color" : null,
227
+ boxShadowTransition ? "box-shadow" : null
228
+ ].filter(isPresent)
229
+ );
230
+ }
231
+ return createInternal({ toCSS });
232
+ }
233
+
234
+ // src/builders/colors.ts
235
+ function targetProperty(target) {
236
+ return target === "bg" ? "background-color" : "color";
237
+ }
238
+ var createColorCss = (_theme) => (target, color, effects = []) => {
239
+ function toCSS() {
240
+ return {
241
+ [targetProperty(target)]: variable(
242
+ customPropertyToken2(color.toString())
243
+ ),
244
+ ...effects.filter(isSupportedEffect).reduce(
245
+ (acc, effect) => ({
246
+ ...acc,
247
+ ...onEffectPseudo(effect, {
248
+ [targetProperty(target)]: variable(
249
+ customPropertyToken2(color.toString(), [effect])
250
+ )
251
+ })
252
+ }),
253
+ {}
254
+ )
255
+ };
256
+ }
257
+ return createInternal({
258
+ toCSS,
259
+ context: effects.length > 0 ? target === "font" ? {
260
+ colorTransition: true
261
+ } : {
262
+ backgroundColorTransition: true
263
+ } : {}
264
+ });
265
+ };
266
+ var createGradientColorCss = (theme) => (color, effects = [], direction) => {
267
+ const toLinearGradient = gradient(direction);
268
+ function toCSS(context) {
269
+ const optimized = !shouldCancelHalfLeading(context);
270
+ const duration = dur2(TRANSITION_DURATION);
271
+ if (optimized && effects.length > 0) {
272
+ return {
273
+ position: "relative",
274
+ zIndex: 0,
275
+ overflow: "hidden",
276
+ ...effects.filter(isSupportedEffect).reduce(
277
+ (acc, effect) => ({
278
+ ...acc,
279
+ "&::before": {
280
+ zIndex: -1,
281
+ ...overlayElement,
282
+ transition: `${duration} background-color`
283
+ },
284
+ "&::after": {
285
+ zIndex: -2,
286
+ ...overlayElement,
287
+ ...toLinearGradient(theme.gradientColor[color])
288
+ },
289
+ ...onEffectPseudo(effect, {
290
+ "&::before": {
291
+ backgroundColor: applyEffect2(
292
+ null,
293
+ theme.effect[effect] ?? []
294
+ )
295
+ }
296
+ })
297
+ }),
298
+ {}
299
+ )
300
+ };
301
+ }
302
+ warning(
303
+ effects.length === 0,
304
+ `'Transition' will not be applied. You can get around this by specifying 'preserveHalfLeading' or both 'padding' and 'typograpy'.`
305
+ );
306
+ return {
307
+ ...toLinearGradient(theme.gradientColor[color]),
308
+ ...effects.filter(isSupportedEffect).reduce(
309
+ (acc, effect) => ({
310
+ ...acc,
311
+ ...onEffectPseudo(effect, {
312
+ ...toLinearGradient(
313
+ applyEffectToGradient(theme.effect[effect] ?? [])(
314
+ theme.gradientColor[color]
315
+ )
316
+ )
317
+ })
318
+ }),
319
+ {}
320
+ )
321
+ };
322
+ }
323
+ return createInternal({ toCSS });
324
+ };
325
+ var overlayElement = {
326
+ content: "''",
327
+ display: "block",
328
+ position: "absolute",
329
+ width: "100%",
330
+ height: "100%",
331
+ top: 0,
332
+ left: 0
333
+ };
334
+ function colors(theme) {
335
+ const colors2 = keyof(theme.color);
336
+ const effects = keyof(theme.effect);
337
+ const gradientColors = keyof(theme.gradientColor);
338
+ const colorCss = createColorCss(theme);
339
+ const gradientColorCss = createGradientColorCss(theme);
340
+ const colorObject = defineConstantProperties(
341
+ {},
342
+ {
343
+ bg: objectAssign(
344
+ defineProperties(
345
+ {},
346
+ colors2,
347
+ (color) => definePropertyChains(
348
+ effects,
349
+ (modifiers) => colorCss("bg", color, modifiers)
350
+ )
351
+ ),
352
+ defineProperties(
353
+ {},
354
+ gradientColors,
355
+ (color) => (direction) => definePropertyChains(
356
+ effects,
357
+ (modifiers) => gradientColorCss(color, modifiers, direction)
358
+ )
359
+ )
360
+ ),
361
+ font: defineProperties(
362
+ {},
363
+ colors2,
364
+ (color) => definePropertyChains(
365
+ effects,
366
+ (modifiers) => colorCss("font", color, modifiers)
367
+ )
368
+ )
369
+ }
370
+ );
371
+ return colorObject;
372
+ }
373
+
374
+ // src/builders/elementEffect.ts
375
+ var createElementEffectCss = (theme) => (effects = []) => createInternal({
376
+ toCSS() {
377
+ return effects.filter(isSupportedEffect).reduce(
378
+ (acc, effect) => ({
379
+ ...acc,
380
+ ...onEffectPseudo(effect, {
381
+ opacity: !Array.isArray(
382
+ theme.elementEffect[effect]
383
+ ) && theme.elementEffect[effect]?.type === "opacity" ? theme.elementEffect[effect]?.opacity : unreachable()
384
+ })
385
+ }),
386
+ {}
387
+ );
388
+ }
389
+ });
390
+ function elementEffect(theme) {
391
+ const effectTypes = keyof(
392
+ theme.elementEffect
393
+ );
394
+ const elementEffectCss = createElementEffectCss(theme);
395
+ const elementEffectObject = definePropertyChains(
396
+ effectTypes,
397
+ (modifiers) => elementEffectCss(modifiers)
398
+ );
399
+ return elementEffectObject;
400
+ }
401
+
402
+ // src/builders/outline.ts
403
+ import { px as px2, notDisabledSelector as notDisabledSelector2 } from "@charcoal-ui/utils";
404
+ var outlineType = ["focus"];
405
+ var outlineCss = (weight, color) => ({
406
+ boxShadow: `0 0 0 ${px2(weight)} ${color}`
407
+ });
408
+ var createOutlineColorCss = (theme) => (variant, modifiers) => {
409
+ const weight = theme.outline[variant].weight;
410
+ const color = theme.outline[variant].color;
411
+ return createInternal({
412
+ toCSS() {
413
+ return modifiers.includes("focus") ? onFocus(outlineCss(weight, color)) : { "&&": { [notDisabledSelector2]: outlineCss(weight, color) } };
414
+ },
415
+ context: {
416
+ boxShadowTransition: true
417
+ }
418
+ });
419
+ };
420
+ var onFocus = (css2) => ({
421
+ [notDisabledSelector2]: {
422
+ "&:focus, &:active": {
423
+ outline: "none",
424
+ ...css2
425
+ },
426
+ "&:focus:not(:focus-visible), &:active:not(:focus-visible)": {
427
+ outline: "none"
428
+ },
429
+ "&:focus-visible": {
430
+ outline: "none",
431
+ ...css2
432
+ }
433
+ }
434
+ });
435
+ function outline(theme) {
436
+ const outlineCss2 = createOutlineColorCss(theme);
437
+ const outlineObject = defineConstantProperties(
438
+ {},
439
+ {
440
+ outline: defineProperties(
441
+ {},
442
+ keyof(theme.outline),
443
+ (variant) => definePropertyChains(
444
+ outlineType,
445
+ (modifiers) => outlineCss2(variant, modifiers)
446
+ )
447
+ )
448
+ }
449
+ );
450
+ return outlineObject;
451
+ }
452
+
453
+ // src/builders/size.ts
454
+ import { columnSystem } from "@charcoal-ui/foundation";
455
+ import { px as px3 } from "@charcoal-ui/utils";
456
+ var fixedProperties = ["width", "height"];
457
+ var createFixedPxCss = (theme) => (property, size2) => createInternal({
458
+ toCSS() {
459
+ return {
460
+ [property]: size2 === "auto" ? "auto" : px3(theme.spacing[size2])
461
+ };
462
+ }
463
+ });
464
+ var createFixedRelativeCss = (_theme) => (property, amount) => createInternal({
465
+ toCSS() {
466
+ return {
467
+ [property]: amount
468
+ };
469
+ }
470
+ });
471
+ var createFixedColumnCss = (theme) => (property, span) => createInternal({
472
+ toCSS() {
473
+ return {
474
+ [property]: px3(
475
+ columnSystem(span, theme.grid.unit.column, theme.grid.unit.gutter)
476
+ )
477
+ };
478
+ }
479
+ });
480
+ function size(theme) {
481
+ const fixedPxCss = createFixedPxCss(theme);
482
+ const fixedColumnCss = createFixedColumnCss(theme);
483
+ const fixedRelativeCss = createFixedRelativeCss(theme);
484
+ const fixedObject = defineProperties(
485
+ {},
486
+ fixedProperties,
487
+ (property) => defineConstantProperties(
488
+ {},
489
+ {
490
+ px: (size2) => fixedPxCss(property, size2),
491
+ column: (span) => fixedColumnCss(property, span),
492
+ auto: fixedRelativeCss(property, "auto"),
493
+ full: fixedRelativeCss(property, "100%")
494
+ }
495
+ )
496
+ );
497
+ return fixedObject;
498
+ }
499
+
500
+ // src/builders/spacing.ts
501
+ import { px as px4 } from "@charcoal-ui/utils";
502
+ var spacingProperties = ["margin", "padding"];
503
+ var spacingDirections = [
504
+ "top",
505
+ "right",
506
+ "bottom",
507
+ "left",
508
+ "vertical",
509
+ "horizontal",
510
+ "all"
511
+ ];
512
+ function spacingProperty(property, direction) {
513
+ return `${property}-${direction}`;
514
+ }
515
+ var createSpacingCss = (theme) => (property, modifiers) => {
516
+ const { top, right, bottom, left } = modifiers.reduce(
517
+ (acc, [direction, size2]) => {
518
+ if (direction === "all") {
519
+ acc.top = size2;
520
+ acc.right = size2;
521
+ acc.bottom = size2;
522
+ acc.left = size2;
523
+ } else if (direction === "vertical") {
524
+ acc.top = size2;
525
+ acc.bottom = size2;
526
+ } else if (direction === "horizontal") {
527
+ acc.right = size2;
528
+ acc.left = size2;
529
+ } else {
530
+ acc[direction] = size2;
531
+ }
532
+ return acc;
533
+ },
534
+ {}
535
+ );
536
+ const hasVerticalPadding = property === "padding" && top !== void 0 && bottom !== void 0 && top !== "auto" && bottom !== "auto";
537
+ function toCSS({ cancelHalfLeadingPx = 0 }) {
538
+ return {
539
+ ...top !== void 0 && {
540
+ [spacingProperty(property, "top")]: top === "auto" ? "auto" : px4(
541
+ theme.spacing[top] + (hasVerticalPadding ? cancelHalfLeadingPx : 0)
542
+ )
543
+ },
544
+ ...bottom !== void 0 && {
545
+ [spacingProperty(property, "bottom")]: bottom === "auto" ? "auto" : px4(
546
+ theme.spacing[bottom] + (hasVerticalPadding ? cancelHalfLeadingPx : 0)
547
+ )
548
+ },
549
+ ...right !== void 0 && {
550
+ [spacingProperty(property, "right")]: right === "auto" ? "auto" : px4(theme.spacing[right])
551
+ },
552
+ ...left !== void 0 && {
553
+ [spacingProperty(property, "left")]: left === "auto" ? "auto" : px4(theme.spacing[left])
554
+ }
555
+ };
556
+ }
557
+ return createInternal({
558
+ toCSS,
559
+ context: hasVerticalPadding ? { hasVerticalPadding: true } : {}
560
+ });
561
+ };
562
+ function spacing(theme) {
563
+ const spacingCss = createSpacingCss(theme);
564
+ const spacingObject = defineProperties(
565
+ {},
566
+ spacingProperties,
567
+ (spacingProperty2) => defineMethodChains(
568
+ spacingDirections,
569
+ (modifiers) => spacingCss(spacingProperty2, modifiers),
570
+ {}
571
+ )
572
+ );
573
+ return spacingObject;
574
+ }
575
+
576
+ // src/builders/typography.ts
577
+ import { halfLeading, px as px5 } from "@charcoal-ui/utils";
578
+ var createTypographyCss = (theme) => (size2, options = {}) => {
579
+ const {
580
+ preserveHalfLeading = false,
581
+ monospace = false,
582
+ bold = false
583
+ } = options;
584
+ const descriptor = theme.typography.size[size2];
585
+ const margin = -halfLeading(descriptor);
586
+ function toCSS(context) {
587
+ return {
588
+ fontSize: px5(descriptor.fontSize),
589
+ lineHeight: px5(descriptor.lineHeight),
590
+ ...monospace && {
591
+ fontFamily: "monospace"
592
+ },
593
+ ...bold && {
594
+ fontWeight: "bold"
595
+ },
596
+ ...shouldCancelHalfLeading(context) && {
597
+ display: "flow-root",
598
+ "&::before": {
599
+ ...leadingCancel,
600
+ marginTop: px5(margin)
601
+ },
602
+ "&::after": {
603
+ ...leadingCancel,
604
+ marginBottom: px5(margin)
605
+ }
606
+ }
607
+ };
608
+ }
609
+ return createInternal({
610
+ toCSS,
611
+ context: !preserveHalfLeading ? {
612
+ cancelHalfLeadingPx: margin
613
+ } : {}
614
+ });
615
+ };
616
+ var leadingCancel = {
617
+ display: "block",
618
+ width: 0,
619
+ height: 0,
620
+ content: `''`
621
+ };
622
+ var typographyModifiers = [
623
+ "monospace",
624
+ "bold",
625
+ "preserveHalfLeading"
626
+ ];
627
+ function typography(theme) {
628
+ const typographyCss = createTypographyCss(theme);
629
+ const typographyObject = defineProperties(
630
+ {},
631
+ ["typography"],
632
+ (_) => (size2) => definePropertyChains(
633
+ typographyModifiers,
634
+ (modifiers) => typographyCss(size2, {
635
+ preserveHalfLeading: modifiers.includes("preserveHalfLeading"),
636
+ monospace: modifiers.includes("monospace"),
637
+ bold: modifiers.includes("bold")
638
+ })
639
+ )
640
+ );
641
+ return typographyObject;
642
+ }
643
+
644
+ // src/builders/o.ts
645
+ function createO(theme) {
646
+ return objectAssign(
647
+ colors(theme),
648
+ typography(theme),
649
+ spacing(theme),
650
+ size(theme),
651
+ elementEffect(theme),
652
+ border(theme),
653
+ borderRadius(theme),
654
+ outline(theme)
655
+ );
656
+ }
657
+
658
+ // src/TokenInjector.tsx
659
+ import React from "react";
660
+ import { createGlobalStyle, css } from "styled-components";
661
+ var GlobalStyle = createGlobalStyle`
662
+ ${({
663
+ themeMap,
664
+ background
665
+ }) => Object.entries(themeMap).map(
666
+ ([key, theme]) => key.startsWith("@media") ? css`
667
+ ${key} {
668
+ :root {
669
+ ${background !== void 0 && css`
670
+ background-color: ${theme.color[background]};
671
+ `}
672
+ ${defineColorVariableCSS(theme)}
673
+ }
674
+ }
675
+ ` : css`
676
+ /* stylelint-disable-next-line no-duplicate-selectors */
677
+ ${key} {
678
+ ${background !== void 0 && css`
679
+ background-color: ${theme.color[background]};
680
+ `}
681
+ ${defineColorVariableCSS(theme)}
682
+ }
683
+ `
684
+ )}
685
+ `;
686
+ function TokenInjector({
687
+ theme: themeMap,
688
+ background
689
+ }) {
690
+ return /* @__PURE__ */ React.createElement(GlobalStyle, { themeMap, background });
691
+ }
692
+ var defineColorVariableCSS = (theme) => Object.entries(defineThemeVariables(theme.color)({ theme })).map(([varName, value]) => variableDefinition(varName, value.toString())).join(";");
693
+ var variableDefinition = (prop, value) => `${prop}: ${value}`;
694
+
695
+ // src/helper.ts
696
+ import { useEffect, useMemo, useState } from "react";
697
+ var LOCAL_STORAGE_KEY = "charcoal-theme";
698
+ var DEFAULT_ROOT_ATTRIBUTE = "theme";
699
+ var keyStringRegExp = new RegExp(/^(\w|-)+$/);
700
+ function assertKeyString(key) {
701
+ if (!keyStringRegExp.test(key)) {
702
+ throw new Error(`Unexpected key :${key}, expect: /^(\\w|-)+$/`);
703
+ }
704
+ }
705
+ var themeSetter = (attr = DEFAULT_ROOT_ATTRIBUTE) => (theme) => {
706
+ assertKeyString(attr);
707
+ if (theme !== void 0) {
708
+ document.documentElement.dataset[attr] = theme;
709
+ } else {
710
+ delete document.documentElement.dataset[attr];
711
+ }
712
+ };
713
+ function themeSelector(theme, attr) {
714
+ return `:root[data-${attr ?? DEFAULT_ROOT_ATTRIBUTE}='${theme}']`;
715
+ }
716
+ function prefersColorScheme(theme) {
717
+ return `@media (prefers-color-scheme: ${theme})`;
718
+ }
719
+ function useThemeSetter({
720
+ key = LOCAL_STORAGE_KEY,
721
+ setter = themeSetter()
722
+ } = {}) {
723
+ const [theme, , system] = useTheme(key);
724
+ useEffect(() => {
725
+ if (theme === void 0) {
726
+ return;
727
+ }
728
+ setter(system ? void 0 : theme);
729
+ }, [setter, system, theme]);
730
+ }
731
+ function getThemeSync(key = LOCAL_STORAGE_KEY) {
732
+ const theme = localStorage.getItem(key);
733
+ return theme;
734
+ }
735
+ var useTheme = (key = LOCAL_STORAGE_KEY) => {
736
+ assertKeyString(key);
737
+ const isDark = useMedia("(prefers-color-scheme: dark)");
738
+ const media = isDark !== void 0 ? isDark ? "dark" : "light" : void 0;
739
+ const [local, setTheme, ready] = useLocalStorage(key);
740
+ const theme = !ready || media === void 0 ? void 0 : local ?? media;
741
+ const system = local === void 0;
742
+ return [theme, setTheme, system];
743
+ };
744
+ function useLocalStorage(key, defaultValue) {
745
+ const [ready, setReady] = useState(false);
746
+ const [state, setState] = useState();
747
+ const defaultValueMemo = useMemo(() => defaultValue?.(), [defaultValue]);
748
+ useEffect(() => {
749
+ fetch();
750
+ window.addEventListener("storage", handleStorage);
751
+ return () => {
752
+ window.removeEventListener("storage", handleStorage);
753
+ };
754
+ });
755
+ const handleStorage = (e) => {
756
+ if (e.storageArea !== localStorage) {
757
+ return;
758
+ }
759
+ if (e.key !== key) {
760
+ return;
761
+ }
762
+ fetch();
763
+ };
764
+ const fetch = () => {
765
+ const raw = localStorage.getItem(key);
766
+ setState((raw !== null ? deserialize(raw) : null) ?? defaultValueMemo);
767
+ setReady(true);
768
+ };
769
+ const set = (value) => {
770
+ if (value === void 0) {
771
+ localStorage.removeItem(key);
772
+ } else {
773
+ const raw = serialize(value);
774
+ localStorage.setItem(key, raw);
775
+ }
776
+ const event = new StorageEvent("storage", {
777
+ bubbles: true,
778
+ cancelable: false,
779
+ key,
780
+ url: location.href,
781
+ storageArea: localStorage
782
+ });
783
+ dispatchEvent(event);
784
+ };
785
+ return [state ?? defaultValueMemo, set, ready];
786
+ }
787
+ function deserialize(raw) {
788
+ try {
789
+ return JSON.parse(raw);
790
+ } catch {
791
+ return raw;
792
+ }
793
+ }
794
+ function serialize(value) {
795
+ if (typeof value === "string") {
796
+ return value;
797
+ } else {
798
+ return JSON.stringify(value);
799
+ }
800
+ }
801
+ function useMedia(query) {
802
+ const [match, setState] = useState();
803
+ useEffect(() => {
804
+ const matcher = window.matchMedia(query);
805
+ const onChange = () => {
806
+ setState(matcher.matches);
807
+ };
808
+ matcher.addEventListener("change", onChange);
809
+ setState(matcher.matches);
810
+ return () => {
811
+ matcher.removeEventListener("change", onChange);
812
+ };
813
+ }, [query]);
814
+ return match;
815
+ }
816
+
817
+ // src/SetThemeScript.tsx
818
+ import React2 from "react";
819
+ function makeSetThemeScriptCode({
820
+ localStorageKey = defaultProps.localStorageKey,
821
+ rootAttribute = defaultProps.rootAttribute
822
+ } = defaultProps) {
823
+ assertKeyString(localStorageKey);
824
+ assertKeyString(rootAttribute);
825
+ return `'use strict';
826
+ (function () {
827
+ var localStorageKey = '${localStorageKey}'
828
+ var rootAttribute = '${rootAttribute}'
829
+ var currentTheme = localStorage.getItem(localStorageKey);
830
+ if (currentTheme) {
831
+ document.documentElement.dataset[rootAttribute] = currentTheme;
832
+ }
833
+ })();
834
+ `;
835
+ }
836
+ function SetThemeScript(props) {
837
+ const src = makeSetThemeScriptCode(props);
838
+ return /* @__PURE__ */ React2.createElement(
839
+ "script",
840
+ {
841
+ dangerouslySetInnerHTML: {
842
+ __html: src
843
+ }
844
+ }
845
+ );
846
+ }
847
+ var defaultProps = {
848
+ localStorageKey: LOCAL_STORAGE_KEY,
849
+ rootAttribute: DEFAULT_ROOT_ATTRIBUTE
850
+ };
851
+ SetThemeScript.defaultProps = defaultProps;
852
+
853
+ // src/index.ts
854
+ var nonBlank = (value) => isPresent(value) && value !== false;
855
+ function createTheme(_styled) {
856
+ return function theme(specFn) {
857
+ return function interpolate({ theme: theme2 }) {
858
+ if (!isPresent(theme2)) {
859
+ throw noThemeProvider;
860
+ }
861
+ const internals = [
862
+ ...wrapArray(
863
+ specFn(createO(theme2))
864
+ ),
865
+ transition(theme2)
866
+ ].filter(nonBlank);
867
+ return toCSSObjects(internals);
868
+ };
869
+ };
870
+ }
871
+ export {
872
+ SetThemeScript,
873
+ TokenInjector,
874
+ createTheme,
875
+ defineThemeVariables,
876
+ getThemeSync,
877
+ makeSetThemeScriptCode,
878
+ prefersColorScheme,
879
+ themeSelector,
880
+ themeSetter,
881
+ useLocalStorage,
882
+ useMedia,
883
+ useTheme,
884
+ useThemeSetter
885
+ };
886
+ //# sourceMappingURL=index.esm.js.map