@charcoal-ui/styled 2.5.0 → 2.7.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 (56) 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 +9 -9
  5. package/dist/builders/border.d.ts.map +1 -1
  6. package/dist/builders/borderRadius.d.ts +6 -6
  7. package/dist/builders/colors.d.ts +12 -12
  8. package/dist/builders/colors.d.ts.map +1 -1
  9. package/dist/builders/elementEffect.d.ts +6 -6
  10. package/dist/builders/o.d.ts +113 -114
  11. package/dist/builders/o.d.ts.map +1 -1
  12. package/dist/builders/outline.d.ts +9 -9
  13. package/dist/builders/outline.d.ts.map +1 -1
  14. package/dist/builders/size.d.ts +22 -22
  15. package/dist/builders/size.d.ts.map +1 -1
  16. package/dist/builders/spacing.d.ts +14 -14
  17. package/dist/builders/spacing.d.ts.map +1 -1
  18. package/dist/builders/transition.d.ts +6 -6
  19. package/dist/builders/typography.d.ts +10 -10
  20. package/dist/defineThemeVariables.test.d.ts +1 -1
  21. package/dist/factories/lib.d.ts +88 -88
  22. package/dist/factories/lib.d.ts.map +1 -1
  23. package/dist/helper.d.ts +38 -38
  24. package/dist/helper.d.ts.map +1 -1
  25. package/dist/index.cjs.js +918 -0
  26. package/dist/index.cjs.js.map +1 -0
  27. package/dist/index.d.ts +128 -128
  28. package/dist/index.d.ts.map +1 -1
  29. package/dist/index.esm.js +886 -0
  30. package/dist/index.esm.js.map +1 -0
  31. package/dist/index.story.d.ts +18 -25
  32. package/dist/index.story.d.ts.map +1 -1
  33. package/dist/index.test.d.ts +1 -1
  34. package/dist/internals/index.d.ts +41 -41
  35. package/dist/storyHelper.d.ts +9 -0
  36. package/dist/storyHelper.d.ts.map +1 -0
  37. package/dist/util.d.ts +100 -100
  38. package/dist/util.d.ts.map +1 -1
  39. package/package.json +16 -16
  40. package/src/builders/border.ts +1 -1
  41. package/src/builders/colors.ts +1 -1
  42. package/src/builders/o.ts +1 -8
  43. package/src/builders/outline.ts +1 -1
  44. package/src/builders/size.ts +1 -1
  45. package/src/builders/spacing.ts +2 -2
  46. package/src/index.story.tsx +1 -18
  47. package/src/index.test.tsx +2 -1
  48. package/src/index.ts +1 -12
  49. package/src/storyHelper.ts +18 -0
  50. package/src/util.ts +1 -1
  51. package/dist/index.cjs +0 -1174
  52. package/dist/index.cjs.map +0 -1
  53. package/dist/index.modern.js +0 -989
  54. package/dist/index.modern.js.map +0 -1
  55. package/dist/index.module.js +0 -1157
  56. package/dist/index.module.js.map +0 -1
@@ -1,989 +0,0 @@
1
- import { filterObject, flatMapObject, customPropertyToken, applyEffect, notDisabledSelector, disabledSelector, px, dur, gradient, applyEffectToGradient, halfLeading } from '@charcoal-ui/utils';
2
- import warning from 'warning';
3
- import { columnSystem } from '@charcoal-ui/foundation';
4
- import React, { useEffect, useState, useMemo } from 'react';
5
- import { createGlobalStyle, css } from 'styled-components';
6
-
7
- function _extends() {
8
- _extends = Object.assign ? Object.assign.bind() : function (target) {
9
- for (var i = 1; i < arguments.length; i++) {
10
- var source = arguments[i];
11
-
12
- for (var key in source) {
13
- if (Object.prototype.hasOwnProperty.call(source, key)) {
14
- target[key] = source[key];
15
- }
16
- }
17
- }
18
-
19
- return target;
20
- };
21
- return _extends.apply(this, arguments);
22
- }
23
-
24
- function unreachable(value) {
25
- throw new Error(arguments.length === 0 ? 'unreachable' : `unreachable (${JSON.stringify(value)})`);
26
- }
27
- /**
28
- * Check whether a value is non-null and non-undefined
29
- *
30
- * @param value nullable
31
- */
32
-
33
- const isPresent = value => value != null; // eslint-disable-next-line @typescript-eslint/no-explicit-any
34
-
35
- function objectAssign(...sources) {
36
- return Object.assign({}, ...sources);
37
- }
38
- /**
39
- * Object.keys の返り値の型を厳しめにしてくれるやつ。
40
- *
41
- * ジェネリクスは基本的に明示して使うことを推奨。
42
- *
43
- * このライブラリでは Theme オブジェクトのジェネリクスを引き回すケースが多く、
44
- * ジェネリクスを省略するといつのまにか keys の返り値が `string | number | symbol` になりがちなので
45
- *
46
- * @param obj - キーを取りたいオブジェクト。ジェネリクスを省略したとき `never[]` のような使えない型が返って欲しい
47
- */
48
-
49
- function keyof(obj) {
50
- return Object.keys(obj);
51
- }
52
- /**
53
- * 配列じゃなかったら配列にする
54
- */
55
-
56
- function wrapArray(value) {
57
- return Array.isArray(value) ? value : [value];
58
- }
59
- const noThemeProvider = new Error('`theme` is invalid. `<ThemeProvider>` is not likely mounted.');
60
- /**
61
- * 子孫要素で使われるカラーテーマの CSS Variables を上書きする
62
- *
63
- * @params colorParams - 上書きしたい色の定義( `theme.color` の一部だけ書けば良い )
64
- * @params effectParams - effect の定義を上書きしたい場合は渡す(必須ではない)
65
- *
66
- * @example
67
- * ```tsx
68
- * const LocalTheme = styled.div`
69
- * ${defineThemeVariables({ text1: '#ff0000' })}
70
- * // `text1` is now defined as red
71
- * ${theme((o) => [o.font.text1])}
72
- * `
73
- * ```
74
- */
75
-
76
- function defineThemeVariables(colorParams, effectParams) {
77
- return function toCssObject(props) {
78
- if (!isPresent(props.theme)) {
79
- throw noThemeProvider;
80
- }
81
-
82
- const colors = filterObject(colorParams, isPresent); // flatMapObject の中で毎回 Object.entries を呼ぶのは無駄なので外で呼ぶ
83
-
84
- const effects = Object.entries(_extends({}, props.theme.effect, effectParams));
85
- return flatMapObject(colors, (colorKey, color) => [[customPropertyToken(colorKey), color], ...effects.map(([effectKey, effect]) => [customPropertyToken(colorKey, [effectKey]), applyEffect(color, [effect])])]);
86
- };
87
- }
88
- function isSupportedEffect(effect) {
89
- return ['hover', 'press', 'disabled'].includes(effect);
90
- }
91
- const variable = value => `var(${value})`;
92
- function onEffectPseudo(effect, css) {
93
- return effect === 'hover' ? {
94
- '&:hover': {
95
- [notDisabledSelector]: css
96
- }
97
- } : effect === 'press' ? {
98
- '&:active': {
99
- [notDisabledSelector]: css
100
- }
101
- } : // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
102
- effect === 'disabled' ? {
103
- [disabledSelector]: css
104
- } : unreachable(effect);
105
- }
106
-
107
- /**
108
- * 絶対にこれを export してはいけない
109
- *
110
- * さもないと `o.bg[internalSym]` みたいな叩き方が可能になってしまう(補完にも意図せず出てしまう)
111
- */
112
- const internalSym = Symbol('internal');
113
- /**
114
- * CSSObject に変換可能なオブジェクトを作成する
115
- *
116
- * 実際に CSSObject に変換するには外部から `__DO_NOT_USE_GET_INTERNAL__` を使わなければならない
117
- *
118
- * これ以降メソッドチェーンが続いてもいいし、続かなくても良い
119
- */
120
-
121
- function createInternal({
122
- toCSS,
123
- context = {}
124
- }) {
125
- return {
126
- [internalSym]: {
127
- toCSS,
128
- context
129
- }
130
- };
131
- }
132
-
133
- function __DO_NOT_USE_ACCESS_PRIVATE_PROPERTY__(internal) {
134
- return internal[internalSym];
135
- } // half-leadingをキャンセルするとき && 垂直方向のpaddingが無い時
136
- // -> before/afterを入れる
137
-
138
-
139
- const shouldCancelHalfLeading = ({
140
- cancelHalfLeadingPx,
141
- hasVerticalPadding: _hasVerticalPadding = false
142
- }) => cancelHalfLeadingPx !== undefined && !_hasVerticalPadding;
143
- /**
144
- * 個別の Internal( o.〇〇 の返り値 )が提出した context の中身を1つの context にまとめる
145
- */
146
-
147
- function getContext(internals) {
148
- return internals.reduce((context, internal) => _extends({}, context, __DO_NOT_USE_ACCESS_PRIVATE_PROPERTY__(internal).context), {});
149
- }
150
- /**
151
- * 全ユーザー定義からコンテキスト生成し、styled-components 向けに CSSObject を構築
152
- */
153
-
154
- function toCSSObjects(internals) {
155
- // 1パス目
156
- // 全ユーザー定義を舐めて相互に影響し合う定義をチェックし、その結果(コンテキスト)を取得
157
- const context = getContext(internals); // 2パス目
158
- // コンテキストを見ながら最適化されたCSSを構築
159
-
160
- return internals.map(v => __DO_NOT_USE_ACCESS_PRIVATE_PROPERTY__(v).toCSS(context));
161
- }
162
-
163
- /**
164
- * 配列で指定したプロパティを動的に生やす
165
- *
166
- * @param source 拡張するオブジェクト
167
- * @param member オブジェクトに生やすプロパティ一覧
168
- * @param chain プロパティに格納される値を生成する関数
169
- *
170
- * @example
171
- *
172
- * const o = factory({}, ['red', 'blue'],
173
- * color => hex(color)
174
- * )
175
- *
176
- * console.log(o.red) //=> #ff0000
177
- */
178
-
179
- const defineProperties = (source, member, chain) => Object.defineProperties(source, Object.fromEntries(member.map(key => [key, {
180
- get: () => chain(key),
181
- enumerable: true,
182
- configurable: true
183
- }])));
184
- /**
185
- * 配列で指定した名前のメソッドを動的に生やす
186
- *
187
- * @param source 拡張するオブジェクト
188
- * @param member オブジェクトに生やすメソッド名一覧
189
- * @param chain メソッドの戻り値になる値を生成する関数
190
- *
191
- * @example
192
- *
193
- * const o = defineMethods({}, ['red', 'blue'],
194
- * (color, alpha: number) => hex(color, alpha)
195
- * )
196
- *
197
- * console.log(o.red(0.5)) //=> #ff000077
198
- */
199
-
200
- const defineMethods = (source, member, chain) => Object.defineProperties(source, Object.fromEntries(member.map(key => [key, {
201
- value: (...args) => chain(key, ...args),
202
- enumerable: true,
203
- configurable: true
204
- }])));
205
- /**
206
- * オブジェクトで指定したプロパティ名と値を動的に生やす
207
- *
208
- * @param source 拡張するオブジェクト
209
- * @param def オブジェクトに生やす定義(プロパティ名と値)
210
- *
211
- * @example
212
- *
213
- * const o = defineConstantProperties({}, {
214
- * red: '#f00',
215
- * blue: '#00f',
216
- * })
217
- *
218
- * console.log(o.red) //=> #f00
219
- */
220
-
221
- const defineConstantProperties = (source, def) => defineProperties(source, Object.keys(def), key => def[key]);
222
- /**
223
- * 配列で指定したモディファイア(プロパティ)をチェーン可能な再帰オブジェクトを動的に生やす
224
- *
225
- * @param modifiers オブジェクトに生やすモディファイヤ一覧
226
- * @param source 指定されたモディファイヤの一覧から値を生成する関数
227
- *
228
- * @example
229
- *
230
- * const o = definePropertyChains(['red', 'blue'],
231
- * modifiers => modifiers.map(color => hex(color)).join(',')
232
- * )
233
- *
234
- * console.log(o.red.blue) => #f00,#00f
235
- */
236
-
237
- const definePropertyChains = (modifiers, source) => function definePropertiesRecursively(applied) {
238
- const notApplied = modifiers.filter(v => !applied.includes(v));
239
- return defineProperties(source(applied), notApplied, modifier => notApplied.length === 0 ? unreachable() : definePropertiesRecursively([...applied, modifier]));
240
- }([]);
241
- /**
242
- * 配列で指定したモディファイア(メソッド)をチェーン可能な再帰オブジェクトを動的に生やす
243
- *
244
- * @param modifiers オブジェクトに生やすモディファイヤ一覧
245
- * @param source 指定されたモディファイヤの一覧から値を生成する関数
246
- * @param _inferPhantom 関数形式のモディファイヤの引数型を推論するためのメタタイプ(引数の個数に合わせてタプルで指定する)
247
- *
248
- * @example
249
- *
250
- * const o = defineMethodChains(['red', 'blue'],
251
- * modifiers => modifiers.map(([color, alpha]) => hex(color, alpha)).join(',')
252
- * , {} as [number])
253
- *
254
- * console.log(o.red(0.5).blue(1)) => #ff000077,#0000ffff
255
- */
256
-
257
- const defineMethodChains = (modifiers, source, ..._inferPhantom) => function defineMethodsRecursively(applied) {
258
- const notApplied = modifiers.filter(v => !applied.map(([w]) => w).includes(v));
259
- return defineMethods(source(applied), notApplied, (modifier, ...args) => notApplied.length === 0 ? unreachable() : defineMethodsRecursively([...applied, [modifier, ...args]]));
260
- }([]);
261
-
262
- const borderDirections = ['top', 'right', 'bottom', 'left'];
263
-
264
- function borderProperty(direction) {
265
- return `border-${direction}`;
266
- }
267
-
268
- function borderShorthand(color) {
269
- return `solid 1px ${color}`;
270
- }
271
-
272
- const createBorderCss = theme => (variant, directions) => {
273
- const all = directions.length === 0;
274
- const value = borderShorthand(theme.border[variant].color);
275
- return createInternal({
276
- toCSS() {
277
- return _extends({}, all ? {
278
- border: value
279
- } : directions.reduce((acc, direction) => _extends({}, acc, {
280
- [borderProperty(direction)]: value
281
- }), {}));
282
- }
283
-
284
- });
285
- };
286
- function border(theme) {
287
- const borderTypes = keyof(theme.border);
288
- const borderCss = createBorderCss(theme);
289
- const borderObject = defineConstantProperties({}, {
290
- border: defineProperties({}, borderTypes, variant => definePropertyChains(borderDirections, modifiers => borderCss(variant, modifiers)))
291
- });
292
- return borderObject;
293
- }
294
-
295
- const createBorderRadiusCss = theme => size => {
296
- return createInternal({
297
- toCSS() {
298
- return {
299
- borderRadius: px(theme.borderRadius[size])
300
- };
301
- }
302
-
303
- });
304
- };
305
- function borderRadius(theme) {
306
- // 角丸
307
- const borderRadiusCss = createBorderRadiusCss(theme);
308
- const borderRadiusObject = defineConstantProperties({}, {
309
- borderRadius: radius => borderRadiusCss(radius)
310
- });
311
- return borderRadiusObject;
312
- }
313
-
314
- const TRANSITION_DURATION = 0.2;
315
- /**
316
- * context の状態を元に transition を追加する。必ず一番最後に呼ぶ
317
- */
318
-
319
- function transition(_theme) {
320
- const duration = dur(TRANSITION_DURATION);
321
-
322
- const transition = property => ({
323
- transition: property.map(v => `${duration} ${v}`).join(', ')
324
- });
325
-
326
- function toCSS({
327
- colorTransition = false,
328
- backgroundColorTransition = false,
329
- boxShadowTransition = false
330
- }) {
331
- return transition([colorTransition ? 'color' : null, backgroundColorTransition ? 'background-color' : null, boxShadowTransition ? 'box-shadow' : null].filter(isPresent));
332
- }
333
-
334
- return createInternal({
335
- toCSS
336
- });
337
- }
338
-
339
- function targetProperty(target) {
340
- return target === 'bg' ? 'background-color' : 'color';
341
- }
342
-
343
- const createColorCss = _theme => (target, color, effects = []) => {
344
- function toCSS() {
345
- return _extends({
346
- [targetProperty(target)]: variable(customPropertyToken(color.toString()))
347
- }, effects.filter(isSupportedEffect).reduce((acc, effect) => _extends({}, acc, onEffectPseudo(effect, {
348
- [targetProperty(target)]: variable(customPropertyToken(color.toString(), [effect]))
349
- })), {}));
350
- }
351
-
352
- return createInternal({
353
- toCSS,
354
- context: effects.length > 0 ? target === 'font' ? {
355
- colorTransition: true
356
- } : {
357
- backgroundColorTransition: true
358
- } : {}
359
- });
360
- };
361
- const createGradientColorCss = theme => (color, effects = [], direction) => {
362
- const toLinearGradient = gradient(direction);
363
-
364
- function toCSS(context) {
365
- const optimized = !shouldCancelHalfLeading(context);
366
- const duration = dur(TRANSITION_DURATION);
367
-
368
- if (optimized && effects.length > 0) {
369
- return _extends({
370
- position: 'relative',
371
- zIndex: 0,
372
- overflow: 'hidden'
373
- }, effects.filter(isSupportedEffect).reduce((acc, effect) => {
374
- var _theme$effect$effect;
375
-
376
- return _extends({}, acc, {
377
- '&::before': _extends({
378
- zIndex: -1
379
- }, overlayElement, {
380
- transition: `${duration} background-color`
381
- }),
382
- '&::after': _extends({
383
- zIndex: -2
384
- }, overlayElement, toLinearGradient(theme.gradientColor[color]))
385
- }, onEffectPseudo(effect, {
386
- '&::before': {
387
- backgroundColor: applyEffect(null, (_theme$effect$effect = theme.effect[effect]) != null ? _theme$effect$effect : [])
388
- }
389
- }));
390
- }, {}));
391
- }
392
-
393
- warning(effects.length === 0, // eslint-disable-next-line max-len
394
- `'Transition' will not be applied. You can get around this by specifying 'preserveHalfLeading' or both 'padding' and 'typograpy'.`);
395
- return _extends({}, toLinearGradient(theme.gradientColor[color]), effects.filter(isSupportedEffect).reduce((acc, effect) => {
396
- var _theme$effect$effect2;
397
-
398
- return _extends({}, acc, onEffectPseudo(effect, _extends({}, toLinearGradient(applyEffectToGradient((_theme$effect$effect2 = theme.effect[effect]) != null ? _theme$effect$effect2 : [])(theme.gradientColor[color])))));
399
- }, {}));
400
- }
401
-
402
- return createInternal({
403
- toCSS
404
- });
405
- };
406
- const overlayElement = {
407
- content: "''",
408
- display: 'block',
409
- position: 'absolute',
410
- width: '100%',
411
- height: '100%',
412
- top: 0,
413
- left: 0
414
- };
415
- function colors(theme) {
416
- const colors = keyof(theme.color);
417
- const effects = keyof(theme.effect); // 色
418
-
419
- const gradientColors = keyof(theme.gradientColor);
420
- const colorCss = createColorCss();
421
- const gradientColorCss = createGradientColorCss(theme);
422
- const colorObject = defineConstantProperties({}, {
423
- bg: objectAssign(defineProperties({}, colors, color => definePropertyChains(effects, modifiers => colorCss('bg', color, modifiers))), defineProperties({}, gradientColors, color => direction => definePropertyChains(effects, modifiers => gradientColorCss(color, modifiers, direction)))),
424
- font: defineProperties({}, colors, color => definePropertyChains(effects, modifiers => colorCss('font', color, modifiers)))
425
- });
426
- return colorObject;
427
- }
428
-
429
- const createElementEffectCss = theme => (effects = []) => createInternal({
430
- toCSS() {
431
- return effects.filter(isSupportedEffect).reduce((acc, effect) => {
432
- var _theme$elementEffect$, _theme$elementEffect$2;
433
-
434
- return _extends({}, acc, onEffectPseudo(effect, {
435
- opacity: !Array.isArray(theme.elementEffect[effect]) && ((_theme$elementEffect$ = theme.elementEffect[effect]) == null ? void 0 : _theme$elementEffect$.type) === 'opacity' ? (_theme$elementEffect$2 = theme.elementEffect[effect]) == null ? void 0 : _theme$elementEffect$2.opacity : unreachable()
436
- }));
437
- }, {});
438
- }
439
-
440
- });
441
- function elementEffect(theme) {
442
- const effectTypes = keyof(theme.elementEffect); // 要素へのエフェクト (etc: 透過)
443
-
444
- const elementEffectCss = createElementEffectCss(theme);
445
- const elementEffectObject = definePropertyChains(effectTypes, modifiers => elementEffectCss(modifiers));
446
- return elementEffectObject;
447
- }
448
-
449
- const outlineType = ['focus'];
450
-
451
- const outlineCss = (weight, color) => ({
452
- boxShadow: `0 0 0 ${px(weight)} ${color}`
453
- });
454
-
455
- const createOutlineColorCss = theme => (variant, modifiers) => {
456
- const weight = theme.outline[variant].weight;
457
- const color = theme.outline[variant].color;
458
- return createInternal({
459
- toCSS() {
460
- return modifiers.includes('focus') ? onFocus(outlineCss(weight, color)) : {
461
- '&&': {
462
- [notDisabledSelector]: outlineCss(weight, color)
463
- }
464
- };
465
- },
466
-
467
- context: {
468
- boxShadowTransition: true
469
- }
470
- });
471
- };
472
- /**
473
- * @see https://developer.mozilla.org/ja/docs/Web/CSS/:focus-visible#selectively_showing_the_focus_indicator
474
- */
475
-
476
- const onFocus = css => ({
477
- [notDisabledSelector]: {
478
- '&:focus, &:active': _extends({
479
- outline: 'none'
480
- }, css),
481
- '&:focus:not(:focus-visible), &:active:not(:focus-visible)': {
482
- outline: 'none'
483
- },
484
- '&:focus-visible': _extends({
485
- outline: 'none'
486
- }, css)
487
- }
488
- });
489
-
490
- function outline(theme) {
491
- const outlineCss = createOutlineColorCss(theme);
492
- const outlineObject = defineConstantProperties({}, {
493
- outline: defineProperties({}, keyof(theme.outline), variant => definePropertyChains(outlineType, modifiers => outlineCss(variant, modifiers)))
494
- });
495
- return outlineObject;
496
- }
497
-
498
- const fixedProperties = ['width', 'height'];
499
- const createFixedPxCss = theme => (property, size) => createInternal({
500
- toCSS() {
501
- return {
502
- [property]: size === 'auto' ? 'auto' : px(theme.spacing[size])
503
- };
504
- }
505
-
506
- });
507
- const createFixedRelativeCss = _theme => (property, amount) => createInternal({
508
- toCSS() {
509
- return {
510
- [property]: amount
511
- };
512
- }
513
-
514
- });
515
- const createFixedColumnCss = theme => (property, span) => createInternal({
516
- toCSS() {
517
- return {
518
- [property]: px(columnSystem(span, theme.grid.unit.column, theme.grid.unit.gutter))
519
- };
520
- }
521
-
522
- });
523
- function size(theme) {
524
- const fixedPxCss = createFixedPxCss(theme);
525
- const fixedColumnCss = createFixedColumnCss(theme);
526
- const fixedRelativeCss = createFixedRelativeCss();
527
- const fixedObject = defineProperties({}, fixedProperties, property => defineConstantProperties({}, {
528
- px: size => fixedPxCss(property, size),
529
- column: span => fixedColumnCss(property, span),
530
- auto: fixedRelativeCss(property, 'auto'),
531
- full: fixedRelativeCss(property, '100%')
532
- }));
533
- return fixedObject;
534
- }
535
-
536
- const spacingProperties = ['margin', 'padding'];
537
- const spacingDirections = ['top', 'right', 'bottom', 'left', 'vertical', 'horizontal', 'all'];
538
-
539
- function spacingProperty(property, direction) {
540
- return `${property}-${direction}`;
541
- }
542
-
543
- const createSpacingCss = theme => (property, modifiers) => {
544
- const {
545
- top,
546
- right,
547
- bottom,
548
- left
549
- } = modifiers.reduce((acc, [direction, size]) => {
550
- if (direction === 'all') {
551
- acc.top = size;
552
- acc.right = size;
553
- acc.bottom = size;
554
- acc.left = size;
555
- } else if (direction === 'vertical') {
556
- acc.top = size;
557
- acc.bottom = size;
558
- } else if (direction === 'horizontal') {
559
- acc.right = size;
560
- acc.left = size;
561
- } else {
562
- acc[direction] = size;
563
- }
564
-
565
- return acc;
566
- }, {});
567
- const hasVerticalPadding = property === 'padding' && top !== undefined && bottom !== undefined && top !== 'auto' && bottom !== 'auto';
568
-
569
- function toCSS({
570
- cancelHalfLeadingPx = 0
571
- }) {
572
- return _extends({}, top !== undefined && {
573
- [spacingProperty(property, 'top')]: top === 'auto' ? 'auto' : px(theme.spacing[top] + (hasVerticalPadding ? cancelHalfLeadingPx : 0))
574
- }, bottom !== undefined && {
575
- [spacingProperty(property, 'bottom')]: bottom === 'auto' ? 'auto' : px(theme.spacing[bottom] + (hasVerticalPadding ? cancelHalfLeadingPx : 0))
576
- }, right !== undefined && {
577
- [spacingProperty(property, 'right')]: right === 'auto' ? 'auto' : px(theme.spacing[right])
578
- }, left !== undefined && {
579
- [spacingProperty(property, 'left')]: left === 'auto' ? 'auto' : px(theme.spacing[left])
580
- });
581
- }
582
-
583
- return createInternal({
584
- toCSS,
585
- context: hasVerticalPadding ? {
586
- hasVerticalPadding: true
587
- } : {}
588
- });
589
- };
590
- function spacing(theme) {
591
- const spacingCss = createSpacingCss(theme);
592
- const spacingObject = defineProperties({}, spacingProperties, spacingProperty => defineMethodChains(spacingDirections, modifiers => spacingCss(spacingProperty, modifiers), {} // 推論のためのメタタイプ
593
- ));
594
- return spacingObject;
595
- }
596
-
597
- const createTypographyCss = theme => (size, options = {}) => {
598
- const {
599
- preserveHalfLeading = false,
600
- monospace = false,
601
- bold = false
602
- } = options;
603
- const descriptor = theme.typography.size[size];
604
- const margin = -halfLeading(descriptor);
605
-
606
- function toCSS(context) {
607
- return _extends({
608
- fontSize: px(descriptor.fontSize),
609
- lineHeight: px(descriptor.lineHeight)
610
- }, monospace && {
611
- fontFamily: 'monospace'
612
- }, bold && {
613
- fontWeight: 'bold'
614
- }, shouldCancelHalfLeading(context) && {
615
- // prevent margin collapsing
616
- display: 'flow-root',
617
- // cancel half-leading with negative margin
618
- '&::before': _extends({}, leadingCancel, {
619
- marginTop: px(margin)
620
- }),
621
- '&::after': _extends({}, leadingCancel, {
622
- marginBottom: px(margin)
623
- })
624
- });
625
- }
626
-
627
- return createInternal({
628
- toCSS,
629
- context: !preserveHalfLeading ? {
630
- cancelHalfLeadingPx: margin
631
- } : {}
632
- });
633
- };
634
- const leadingCancel = {
635
- display: 'block',
636
- width: 0,
637
- height: 0,
638
- content: `''`
639
- }; // タイポグラフィ
640
-
641
- const typographyModifiers = [// TODO
642
- 'monospace', 'bold', 'preserveHalfLeading'];
643
- function typography(theme) {
644
- const typographyCss = createTypographyCss(theme);
645
- const typographyObject = defineProperties({}, ['typography'], _ => size => definePropertyChains(typographyModifiers, modifiers => typographyCss(size, {
646
- preserveHalfLeading: modifiers.includes('preserveHalfLeading'),
647
- monospace: modifiers.includes('monospace'),
648
- bold: modifiers.includes('bold')
649
- })));
650
- return typographyObject;
651
- }
652
-
653
- /**
654
- * `theme(o => [...])` の `o` の部分を構築する
655
- *
656
- * @param theme テーマオブジェクト
657
- * @param DO_NOTHING_IT_IS_JUST_CALLED_FOR_TYPE_INFERENCE 型推論のためだけに使う場合にランタイムコストをゼロにするフラグ
658
- */
659
-
660
- function createO(theme, DO_NOTHING_IT_IS_JUST_CALLED_FOR_TYPE_INFERENCE = false) {
661
- if (DO_NOTHING_IT_IS_JUST_CALLED_FOR_TYPE_INFERENCE) {
662
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
663
- return {};
664
- }
665
-
666
- return objectAssign(colors(theme), typography(theme), spacing(theme), size(theme), elementEffect(theme), border(theme), borderRadius(theme), outline(theme));
667
- }
668
-
669
- let _ = t => t,
670
- _t,
671
- _t2,
672
- _t3,
673
- _t4,
674
- _t5;
675
- const GlobalStyle = createGlobalStyle(_t || (_t = _`
676
- ${0}
677
- `), ({
678
- themeMap,
679
- background
680
- }) => Object.entries(themeMap).map(([key, theme]) => key.startsWith('@media') ? css(_t2 || (_t2 = _`
681
- ${0} {
682
- :root {
683
- ${0}
684
- ${0}
685
- }
686
- }
687
- `), key, background !== undefined && css(_t3 || (_t3 = _`
688
- background-color: ${0};
689
- `), theme.color[background]), defineColorVariableCSS(theme)) : css(_t4 || (_t4 = _`
690
- /* stylelint-disable-next-line no-duplicate-selectors */
691
- ${0} {
692
- ${0}
693
- ${0}
694
- }
695
- `), key, background !== undefined && css(_t5 || (_t5 = _`
696
- background-color: ${0};
697
- `), theme.color[background]), defineColorVariableCSS(theme))));
698
- function TokenInjector({
699
- theme: themeMap,
700
- background
701
- }) {
702
- return /*#__PURE__*/React.createElement(GlobalStyle, {
703
- themeMap: themeMap,
704
- background: background
705
- });
706
- }
707
-
708
- const defineColorVariableCSS = theme => Object.entries(defineThemeVariables(theme.color)({
709
- theme
710
- })).map(([varName, value]) => variableDefinition(varName, value.toString())).join(';');
711
-
712
- const variableDefinition = (prop, value) => `${prop}: ${value}`;
713
-
714
- const LOCAL_STORAGE_KEY = 'charcoal-theme';
715
- const DEFAULT_ROOT_ATTRIBUTE = 'theme';
716
- const keyStringRegExp = new RegExp(/^(\w|-)+$/);
717
- /**
718
- * 文字列が英数字_-のみで構成されているか検証する。不正な文字列ならエラーを投げる
719
- * @param key 検証するキー
720
- */
721
-
722
- function assertKeyString(key) {
723
- if (!keyStringRegExp.test(key)) {
724
- throw new Error(`Unexpected key :${key}, expect: /^(\\w|-)+$/`);
725
- }
726
- }
727
- /**
728
- * `<html data-theme="dark">` のような設定を行うデフォルトのセッター
729
- */
730
-
731
- const themeSetter = (attr = DEFAULT_ROOT_ATTRIBUTE) => theme => {
732
- assertKeyString(attr);
733
-
734
- if (theme !== undefined) {
735
- document.documentElement.dataset[attr] = theme;
736
- } else {
737
- delete document.documentElement.dataset[attr];
738
- }
739
- };
740
- /**
741
- * `<html data-theme="dark">` にマッチするセレクタを生成する
742
- */
743
-
744
- function themeSelector(theme, attr) {
745
- return `:root[data-${attr != null ? attr : DEFAULT_ROOT_ATTRIBUTE}='${theme}']`;
746
- }
747
- /**
748
- * prefers-color-scheme を利用する media クエリを生成する
749
- */
750
-
751
- function prefersColorScheme(theme) {
752
- return `@media (prefers-color-scheme: ${theme})`;
753
- }
754
- /**
755
- * LocalStorageからテーマの情報を取得して、変化時にテーマをセットするhooks
756
- */
757
-
758
- function useThemeSetter({
759
- key = LOCAL_STORAGE_KEY,
760
- setter = themeSetter()
761
- } = {}) {
762
- const [theme,, system] = useTheme(key);
763
- useEffect(() => {
764
- if (theme === undefined) {
765
- return;
766
- } // prefers-color-scheme から値を取っている場合にはcssのみで処理したいのでアンセットする
767
-
768
-
769
- setter(system ? undefined : theme);
770
- }, [setter, system, theme]);
771
- }
772
- /**
773
- * 同期的にLocalStorageからテーマを取得するヘルパ
774
- */
775
-
776
- function getThemeSync(key = LOCAL_STORAGE_KEY) {
777
- const theme = localStorage.getItem(key);
778
- return theme;
779
- }
780
- /**
781
- * LocalStorage, prefers-color-scheme からテーマの情報を取得して、現在のテーマを返すhooks
782
- *
783
- * `dark` `light` という名前だけは特別扱いされていて、prefers-color-schemeにマッチした場合に返ります
784
- */
785
-
786
- const useTheme = (key = LOCAL_STORAGE_KEY) => {
787
- assertKeyString(key);
788
- const isDark = useMedia('(prefers-color-scheme: dark)');
789
- const media = isDark !== undefined ? isDark ? 'dark' : 'light' : undefined;
790
- const [local, setTheme, ready] = useLocalStorage(key);
791
- const theme = !ready || media === undefined ? undefined : local != null ? local : media;
792
- const system = local === undefined;
793
- return [theme, setTheme, system];
794
- };
795
- function useLocalStorage(key, defaultValue) {
796
- const [ready, setReady] = useState(false);
797
- const [state, setState] = useState();
798
- const defaultValueMemo = useMemo(() => defaultValue == null ? void 0 : defaultValue(), [defaultValue]);
799
- useEffect(() => {
800
- fetch();
801
- window.addEventListener('storage', handleStorage);
802
- return () => {
803
- window.removeEventListener('storage', handleStorage);
804
- };
805
- });
806
-
807
- const handleStorage = e => {
808
- if (e.storageArea !== localStorage) {
809
- return;
810
- }
811
-
812
- if (e.key !== key) {
813
- return;
814
- }
815
-
816
- fetch();
817
- };
818
-
819
- const fetch = () => {
820
- var _ref;
821
-
822
- const raw = localStorage.getItem(key);
823
- setState((_ref = raw !== null ? deserialize(raw) : null) != null ? _ref : defaultValueMemo);
824
- setReady(true);
825
- };
826
-
827
- const set = value => {
828
- if (value === undefined) {
829
- // undefinedがセットされる場合にはkeyごと削除
830
- localStorage.removeItem(key);
831
- } else {
832
- const raw = serialize(value);
833
- localStorage.setItem(key, raw);
834
- } // 同一ウィンドウではstorageイベントが発火しないので、手動で発火させる
835
-
836
-
837
- const event = new StorageEvent('storage', {
838
- bubbles: true,
839
- cancelable: false,
840
- key,
841
- url: location.href,
842
- storageArea: localStorage
843
- });
844
- dispatchEvent(event);
845
- };
846
-
847
- return [state != null ? state : defaultValueMemo, set, ready];
848
- }
849
-
850
- function deserialize(raw) {
851
- try {
852
- return JSON.parse(raw);
853
- } catch (_unused) {
854
- // syntax error はすべて文字列として扱う
855
- return raw;
856
- }
857
- }
858
-
859
- function serialize(value) {
860
- if (typeof value === 'string') {
861
- return value;
862
- } else {
863
- return JSON.stringify(value);
864
- }
865
- }
866
-
867
- function useMedia(query) {
868
- const [match, setState] = useState();
869
- useEffect(() => {
870
- const matcher = window.matchMedia(query);
871
-
872
- const onChange = () => {
873
- setState(matcher.matches);
874
- };
875
-
876
- matcher.addEventListener('change', onChange);
877
- setState(matcher.matches);
878
- return () => {
879
- matcher.removeEventListener('change', onChange);
880
- };
881
- }, [query]);
882
- return match;
883
- }
884
-
885
- /**
886
- * 同期的にテーマをローカルストレージから取得してhtmlの属性に設定するコードを取得する
887
- * @param props localStorageのキー、htmlのdataになる属性のキーを含むオブジェクト
888
- * @returns ソースコードの文字列
889
- */
890
-
891
- function makeSetThemeScriptCode({
892
- localStorageKey = defaultProps.localStorageKey,
893
- rootAttribute = defaultProps.rootAttribute
894
- } = defaultProps) {
895
- assertKeyString(localStorageKey);
896
- assertKeyString(rootAttribute);
897
- return `'use strict';
898
- (function () {
899
- var localStorageKey = '${localStorageKey}'
900
- var rootAttribute = '${rootAttribute}'
901
- var currentTheme = localStorage.getItem(localStorageKey);
902
- if (currentTheme) {
903
- document.documentElement.dataset[rootAttribute] = currentTheme;
904
- }
905
- })();
906
- `;
907
- }
908
- /**
909
- * 同期的にテーマをローカルストレージから取得してhtmlの属性に設定するスクリプトタグ
910
- * @param props localStorageのキー、htmlのdataになる属性のキーを含むオブジェクト
911
- * @returns
912
- */
913
-
914
- function SetThemeScript(props) {
915
- const src = makeSetThemeScriptCode(props);
916
- return /*#__PURE__*/React.createElement("script", {
917
- dangerouslySetInnerHTML: {
918
- __html: src
919
- }
920
- });
921
- }
922
- const defaultProps = {
923
- localStorageKey: LOCAL_STORAGE_KEY,
924
- rootAttribute: DEFAULT_ROOT_ATTRIBUTE
925
- };
926
- SetThemeScript.defaultProps = defaultProps;
927
-
928
- const nonBlank = value => isPresent(value) && value !== false;
929
- /**
930
- * `theme(o => [...])` の `theme` ユーティリティを構築する
931
- *
932
- * @param _styled - DEPRECATED: styled-componnets の `styled` そのものを渡すとそれを元に型推論ができる。が、型引数を渡す方が型推論が高速になりやすい
933
- *
934
- * @example
935
- *
936
- * import styled from 'styled-components'
937
- * const theme = createTheme(styled)
938
- *
939
- * @example
940
- *
941
- * const theme = createTheme<DefaultTheme>()
942
- */
943
-
944
-
945
- function createTheme(_styled) {
946
- /**
947
- * 本当は `type Builder = ReturnType<createO<T>>` みたいな型を作って、それを o の型にしたい。
948
- * が、styled がつくられた時点の TypeScript ではこういうジェネリクスの使い方ができなかった
949
- * なので代わりに特に意味のない `createO` の呼び出しをやっている
950
- */
951
- createO( // eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-explicit-any
952
- {},
953
- /** DO_NOTHING_IT_IS_JUST_CALLED_FOR_TYPE_INFERENCE = */
954
- true); // ランタイムの `theme(o => [...])` のインターフェースを構築する
955
-
956
- return function theme(specFn) {
957
- // styled-components のテンプレートに埋め込める関数
958
- return function interpolate({
959
- theme
960
- }) {
961
- if (!isPresent(theme)) {
962
- // テーマが入っていない場合は復旧不可能なのでエラーにする
963
- throw noThemeProvider;
964
- }
965
-
966
- const internals = [// ユーザーが定義したルール
967
- ...wrapArray(
968
- /**
969
- * こう書いてはいけない
970
- *
971
- * ❌
972
- * ```ts
973
- * const o = createO(theme)
974
- * const declaration = spec(o)
975
- * ```
976
- *
977
- * `o` を一時変数に入れてしまうと型 `T` の具象化が行われるので関数内に書く
978
- */
979
- specFn(
980
- /** o = */
981
- createO(theme))), // 必ず挿入される共通のルール
982
- transition()].filter(nonBlank);
983
- return toCSSObjects(internals);
984
- };
985
- };
986
- }
987
-
988
- export { SetThemeScript, TokenInjector, createTheme, defineThemeVariables, getThemeSync, makeSetThemeScriptCode, prefersColorScheme, themeSelector, themeSetter, useLocalStorage, useMedia, useTheme, useThemeSetter };
989
- //# sourceMappingURL=index.modern.js.map