@charcoal-ui/styled 4.2.1 → 4.3.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@charcoal-ui/styled",
3
- "version": "4.2.1",
3
+ "version": "4.3.0-beta.0",
4
4
  "license": "Apache-2.0",
5
5
  "types": "./dist/index.d.ts",
6
6
  "main": "./dist/index.cjs.js",
@@ -21,6 +21,7 @@
21
21
  "test": "vitest run --passWithNoTests"
22
22
  },
23
23
  "devDependencies": {
24
+ "@charcoal-ui/react": "4.3.0-beta.0",
24
25
  "@types/react": "^18.3.3",
25
26
  "@types/react-test-renderer": "^18.3.0",
26
27
  "@types/styled-components": "^5.1.21",
@@ -38,12 +39,13 @@
38
39
  "vitest": "^2.0.2"
39
40
  },
40
41
  "dependencies": {
41
- "@charcoal-ui/foundation": "^4.2.1",
42
- "@charcoal-ui/theme": "^4.2.1",
43
- "@charcoal-ui/utils": "^4.2.1",
42
+ "@charcoal-ui/foundation": "4.3.0-beta.0",
43
+ "@charcoal-ui/theme": "4.3.0-beta.0",
44
+ "@charcoal-ui/utils": "4.3.0-beta.0",
44
45
  "warning": "^4.0.3"
45
46
  },
46
47
  "peerDependencies": {
48
+ "@charcoal-ui/react": "workspace:*",
47
49
  "react": ">=17.0.0",
48
50
  "styled-components": ">=5.1.1"
49
51
  },
@@ -59,5 +61,5 @@
59
61
  "url": "https://github.com/pixiv/charcoal.git",
60
62
  "directory": "packages/styled"
61
63
  },
62
- "gitHead": "9a017d7e402dfcf371a5ca9a2b61bcd095467d89"
64
+ "gitHead": "864fc9a6c8ad391df01c7765ab0dff66842c612d"
63
65
  }
@@ -6,6 +6,8 @@ import styled, { ThemeProvider } from 'styled-components'
6
6
  import { Example } from './addThemeUtils.story'
7
7
  import { MyTheme, myTheme } from './storyHelper'
8
8
 
9
+ import type { JSX } from 'react'
10
+
9
11
  function render(children: JSX.Element) {
10
12
  return renderer
11
13
  .create(<ThemeProvider theme={myTheme(light)}>{children}</ThemeProvider>)
package/src/index.ts CHANGED
@@ -14,10 +14,11 @@ export {
14
14
  useThemeSetter,
15
15
  useLocalStorage,
16
16
  useMedia,
17
- } from './helper'
17
+ makeSetThemeScriptCode,
18
+ SetThemeScript,
19
+ } from '@charcoal-ui/react'
18
20
  export { defineThemeVariables } from './util'
19
21
  export { removeHalfLeadingCss } from './utils/typographyCss'
20
- export * from './SetThemeScript'
21
22
 
22
23
  type Blank = null | undefined | false
23
24
 
@@ -1,21 +0,0 @@
1
- interface Props {
2
- localStorageKey: string;
3
- rootAttribute: string;
4
- }
5
- /**
6
- * 同期的にテーマをローカルストレージから取得してhtmlの属性に設定するコードを取得する
7
- * @param props localStorageのキー、htmlのdataになる属性のキーを含むオブジェクト
8
- * @returns ソースコードの文字列
9
- */
10
- export declare function makeSetThemeScriptCode({ localStorageKey, rootAttribute, }?: Partial<Props>): string;
11
- /**
12
- * 同期的にテーマをローカルストレージから取得してhtmlの属性に設定するスクリプトタグ
13
- * @param props localStorageのキー、htmlのdataになる属性のキーを含むオブジェクト
14
- * @returns
15
- */
16
- export declare function SetThemeScript(props: Props): import("react/jsx-runtime").JSX.Element;
17
- export declare namespace SetThemeScript {
18
- var defaultProps: Props;
19
- }
20
- export {};
21
- //# sourceMappingURL=SetThemeScript.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"SetThemeScript.d.ts","sourceRoot":"","sources":["../src/SetThemeScript.tsx"],"names":[],"mappings":"AAMA,UAAU,KAAK;IACb,eAAe,EAAE,MAAM,CAAA;IACvB,aAAa,EAAE,MAAM,CAAA;CACtB;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,EACrC,eAA8C,EAC9C,aAA0C,GAC3C,GAAE,OAAO,CAAC,KAAK,CAAgB,UAa/B;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,KAAK,2CAS1C;yBATe,cAAc"}
package/dist/helper.d.ts DELETED
@@ -1,39 +0,0 @@
1
- export declare const LOCAL_STORAGE_KEY = "charcoal-theme";
2
- export declare const DEFAULT_ROOT_ATTRIBUTE = "theme";
3
- /**
4
- * 文字列が英数字_-のみで構成されているか検証する。不正な文字列ならエラーを投げる
5
- * @param key 検証するキー
6
- */
7
- export declare function assertKeyString(key: string): void;
8
- /**
9
- * `<html data-theme="dark">` のような設定を行うデフォルトのセッター
10
- */
11
- export declare const themeSetter: (attr?: string) => (theme: string | undefined) => void;
12
- /**
13
- * `<html data-theme="dark">` にマッチするセレクタを生成する
14
- */
15
- export declare function themeSelector<T extends string, S extends string = typeof DEFAULT_ROOT_ATTRIBUTE>(theme: T, attr?: S): `:root[data-theme='${T}']` | `:root[data-${S}='${T}']`;
16
- /**
17
- * prefers-color-scheme を利用する media クエリを生成する
18
- */
19
- export declare function prefersColorScheme<T extends 'light' | 'dark'>(theme: T): `@media (prefers-color-scheme: ${T})`;
20
- /**
21
- * LocalStorageからテーマの情報を取得して、変化時にテーマをセットするhooks
22
- */
23
- export declare function useThemeSetter({ key, setter, }?: {
24
- key?: string;
25
- setter?: (theme: string | undefined) => void;
26
- }): void;
27
- /**
28
- * 同期的にLocalStorageからテーマを取得するヘルパ
29
- */
30
- export declare function getThemeSync(key?: string): string | null;
31
- /**
32
- * LocalStorage, prefers-color-scheme からテーマの情報を取得して、現在のテーマを返すhooks
33
- *
34
- * `dark` `light` という名前だけは特別扱いされていて、prefers-color-schemeにマッチした場合に返ります
35
- */
36
- export declare const useTheme: (localStorageKey?: string) => readonly ["light" | "dark" | undefined, (value: "light" | "dark" | undefined) => void, boolean];
37
- export declare function useLocalStorage<T>(key: string, defaultValue?: () => T): readonly [T | undefined, (value: T | undefined) => void, boolean];
38
- export declare function useMedia(query: string): boolean | undefined;
39
- //# sourceMappingURL=helper.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"helper.d.ts","sourceRoot":"","sources":["../src/helper.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,iBAAiB,mBAAmB,CAAA;AACjD,eAAO,MAAM,sBAAsB,UAAU,CAAA;AAI7C;;;GAGG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,QAI1C;AAED;;GAEG;AACH,eAAO,MAAM,WAAW,UACf,MAAM,aACL,MAAM,GAAG,SAAS,SAOzB,CAAA;AAEH;;GAEG;AACH,wBAAgB,aAAa,CAC3B,CAAC,SAAS,MAAM,EAChB,CAAC,SAAS,MAAM,GAAG,OAAO,sBAAsB,EAChD,KAAK,EAAE,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,0DAEnB;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,CAAC,SAAS,OAAO,GAAG,MAAM,EAAE,KAAK,EAAE,CAAC,yCAEtE;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,EAC7B,GAAuB,EACvB,MAAsB,GACvB,GAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,KAAK,IAAI,CAAA;CAAO,QAUrE;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,GAAG,GAAE,MAA0B,iBAG3D;AAED;;;;GAIG;AACH,eAAO,MAAM,QAAQ,qBAAqB,MAAM,oGAS/C,CAAA;AAED,wBAAgB,eAAe,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM,CAAC,oCA6BhD,CAAC,GAAG,SAAS,oBAqBlC;AAmBD,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,uBAoBrC"}
@@ -1,56 +0,0 @@
1
- import {
2
- assertKeyString,
3
- DEFAULT_ROOT_ATTRIBUTE,
4
- LOCAL_STORAGE_KEY,
5
- } from './helper'
6
-
7
- interface Props {
8
- localStorageKey: string
9
- rootAttribute: string
10
- }
11
-
12
- /**
13
- * 同期的にテーマをローカルストレージから取得してhtmlの属性に設定するコードを取得する
14
- * @param props localStorageのキー、htmlのdataになる属性のキーを含むオブジェクト
15
- * @returns ソースコードの文字列
16
- */
17
- export function makeSetThemeScriptCode({
18
- localStorageKey = defaultProps.localStorageKey,
19
- rootAttribute = defaultProps.rootAttribute,
20
- }: Partial<Props> = defaultProps) {
21
- assertKeyString(localStorageKey)
22
- assertKeyString(rootAttribute)
23
- return `'use strict';
24
- (function () {
25
- var localStorageKey = '${localStorageKey}'
26
- var rootAttribute = '${rootAttribute}'
27
- var currentTheme = localStorage.getItem(localStorageKey);
28
- if (currentTheme) {
29
- document.documentElement.dataset[rootAttribute] = currentTheme;
30
- }
31
- })();
32
- `
33
- }
34
-
35
- /**
36
- * 同期的にテーマをローカルストレージから取得してhtmlの属性に設定するスクリプトタグ
37
- * @param props localStorageのキー、htmlのdataになる属性のキーを含むオブジェクト
38
- * @returns
39
- */
40
- export function SetThemeScript(props: Props) {
41
- const src = makeSetThemeScriptCode(props)
42
- return (
43
- <script
44
- dangerouslySetInnerHTML={{
45
- __html: src,
46
- }}
47
- />
48
- )
49
- }
50
-
51
- const defaultProps: Props = {
52
- localStorageKey: LOCAL_STORAGE_KEY,
53
- rootAttribute: DEFAULT_ROOT_ATTRIBUTE,
54
- }
55
-
56
- SetThemeScript.defaultProps = defaultProps
package/src/helper.ts DELETED
@@ -1,180 +0,0 @@
1
- import { useEffect, useMemo, useState } from 'react'
2
-
3
- export const LOCAL_STORAGE_KEY = 'charcoal-theme'
4
- export const DEFAULT_ROOT_ATTRIBUTE = 'theme'
5
-
6
- const keyStringRegExp = new RegExp(/^(\w|-)+$/)
7
-
8
- /**
9
- * 文字列が英数字_-のみで構成されているか検証する。不正な文字列ならエラーを投げる
10
- * @param key 検証するキー
11
- */
12
- export function assertKeyString(key: string) {
13
- if (!keyStringRegExp.test(key)) {
14
- throw new Error(`Unexpected key :${key}, expect: /^(\\w|-)+$/`)
15
- }
16
- }
17
-
18
- /**
19
- * `<html data-theme="dark">` のような設定を行うデフォルトのセッター
20
- */
21
- export const themeSetter =
22
- (attr: string = DEFAULT_ROOT_ATTRIBUTE) =>
23
- (theme: string | undefined) => {
24
- assertKeyString(attr)
25
- if (theme !== undefined) {
26
- document.documentElement.dataset[attr] = theme
27
- } else {
28
- delete document.documentElement.dataset[attr]
29
- }
30
- }
31
-
32
- /**
33
- * `<html data-theme="dark">` にマッチするセレクタを生成する
34
- */
35
- export function themeSelector<
36
- T extends string,
37
- S extends string = typeof DEFAULT_ROOT_ATTRIBUTE
38
- >(theme: T, attr?: S) {
39
- return `:root[data-${attr ?? DEFAULT_ROOT_ATTRIBUTE}='${theme}']` as const
40
- }
41
-
42
- /**
43
- * prefers-color-scheme を利用する media クエリを生成する
44
- */
45
- export function prefersColorScheme<T extends 'light' | 'dark'>(theme: T) {
46
- return `@media (prefers-color-scheme: ${theme})` as const
47
- }
48
-
49
- /**
50
- * LocalStorageからテーマの情報を取得して、変化時にテーマをセットするhooks
51
- */
52
- export function useThemeSetter({
53
- key = LOCAL_STORAGE_KEY,
54
- setter = themeSetter(),
55
- }: { key?: string; setter?: (theme: string | undefined) => void } = {}) {
56
- const [theme, , system] = useTheme(key)
57
-
58
- useEffect(() => {
59
- if (theme === undefined) {
60
- return
61
- }
62
- // prefers-color-scheme から値を取っている場合にはcssのみで処理したいのでアンセットする
63
- setter(system ? undefined : theme)
64
- }, [setter, system, theme])
65
- }
66
-
67
- /**
68
- * 同期的にLocalStorageからテーマを取得するヘルパ
69
- */
70
- export function getThemeSync(key: string = LOCAL_STORAGE_KEY) {
71
- const theme = localStorage.getItem(key)
72
- return theme
73
- }
74
-
75
- /**
76
- * LocalStorage, prefers-color-scheme からテーマの情報を取得して、現在のテーマを返すhooks
77
- *
78
- * `dark` `light` という名前だけは特別扱いされていて、prefers-color-schemeにマッチした場合に返ります
79
- */
80
- export const useTheme = (localStorageKey: string = LOCAL_STORAGE_KEY) => {
81
- assertKeyString(localStorageKey)
82
- const isDark = useMedia('(prefers-color-scheme: dark)')
83
- const media = isDark !== undefined ? (isDark ? 'dark' : 'light') : undefined
84
- const [local, setTheme, ready] =
85
- useLocalStorage<typeof media>(localStorageKey)
86
- const theme = !ready || media === undefined ? undefined : local ?? media
87
- const system = local === undefined
88
- return [theme, setTheme, system] as const
89
- }
90
-
91
- export function useLocalStorage<T>(key: string, defaultValue?: () => T) {
92
- const [ready, setReady] = useState(false)
93
- const [state, setState] = useState<T>()
94
- const defaultValueMemo = useMemo(() => defaultValue?.(), [defaultValue])
95
-
96
- useEffect(() => {
97
- fetch()
98
- window.addEventListener('storage', handleStorage)
99
- return () => {
100
- window.removeEventListener('storage', handleStorage)
101
- }
102
- })
103
-
104
- const handleStorage = (e: StorageEvent) => {
105
- if (e.storageArea !== localStorage) {
106
- return
107
- }
108
- if (e.key !== key) {
109
- return
110
- }
111
- fetch()
112
- }
113
-
114
- const fetch = () => {
115
- const raw = localStorage.getItem(key)
116
- setState((raw !== null ? deserialize(raw) : null) ?? defaultValueMemo)
117
- setReady(true)
118
- }
119
-
120
- const set = (value: T | undefined) => {
121
- if (value === undefined) {
122
- // undefinedがセットされる場合にはkeyごと削除
123
- localStorage.removeItem(key)
124
- } else {
125
- const raw = serialize(value)
126
- localStorage.setItem(key, raw)
127
- }
128
-
129
- // 同一ウィンドウではstorageイベントが発火しないので、手動で発火させる
130
- const event = new StorageEvent('storage', {
131
- bubbles: true,
132
- cancelable: false,
133
- key,
134
- url: location.href,
135
- storageArea: localStorage,
136
- })
137
- dispatchEvent(event)
138
- }
139
-
140
- return [state ?? defaultValueMemo, set, ready] as const
141
- }
142
-
143
- function deserialize<T>(raw: string): T {
144
- try {
145
- return JSON.parse(raw) as T
146
- } catch {
147
- // syntax error はすべて文字列として扱う
148
- return raw as unknown as T
149
- }
150
- }
151
-
152
- function serialize(value: unknown): string {
153
- if (typeof value === 'string') {
154
- return value
155
- } else {
156
- return JSON.stringify(value)
157
- }
158
- }
159
-
160
- export function useMedia(query: string) {
161
- const [match, setState] = useState<boolean>()
162
-
163
- useEffect(() => {
164
- const matcher = window.matchMedia(query)
165
-
166
- const onChange = () => {
167
- setState(matcher.matches)
168
- }
169
-
170
- matcher.addEventListener('change', onChange)
171
-
172
- setState(matcher.matches)
173
-
174
- return () => {
175
- matcher.removeEventListener('change', onChange)
176
- }
177
- }, [query])
178
-
179
- return match
180
- }