@puzzle-ui/theme 0.0.0-stage → 0.1.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 (87) hide show
  1. package/dist/LICENSE +21 -0
  2. package/dist/breakpoints.cjs +10 -0
  3. package/dist/breakpoints.cjs.map +1 -0
  4. package/dist/breakpoints.d.cts +7 -0
  5. package/dist/breakpoints.d.ts +7 -0
  6. package/dist/breakpoints.js +10 -0
  7. package/dist/breakpoints.js.map +1 -0
  8. package/dist/components-context.cjs +19 -0
  9. package/dist/components-context.cjs.map +1 -0
  10. package/dist/components-context.d.cts +8 -0
  11. package/dist/components-context.d.ts +8 -0
  12. package/dist/components-context.js +17 -0
  13. package/dist/components-context.js.map +1 -0
  14. package/dist/components.types.d.cts +46 -0
  15. package/dist/components.types.d.ts +46 -0
  16. package/dist/constants.cjs +567 -0
  17. package/dist/constants.cjs.map +1 -0
  18. package/dist/constants.d.cts +363 -0
  19. package/dist/constants.d.ts +363 -0
  20. package/dist/constants.js +565 -0
  21. package/dist/constants.js.map +1 -0
  22. package/dist/create-theme-css.cjs +7 -0
  23. package/dist/create-theme-css.cjs.map +1 -0
  24. package/dist/create-theme-css.js +7 -0
  25. package/dist/create-theme-css.js.map +1 -0
  26. package/dist/create-theme-variables.cjs +135 -0
  27. package/dist/create-theme-variables.cjs.map +1 -0
  28. package/dist/create-theme-variables.js +134 -0
  29. package/dist/create-theme-variables.js.map +1 -0
  30. package/dist/fonts/constants.cjs +9 -0
  31. package/dist/fonts/constants.cjs.map +1 -0
  32. package/dist/fonts/constants.js +9 -0
  33. package/dist/fonts/constants.js.map +1 -0
  34. package/dist/fonts/create-google-font-url.cjs +27 -0
  35. package/dist/fonts/create-google-font-url.cjs.map +1 -0
  36. package/dist/fonts/create-google-font-url.d.cts +2 -0
  37. package/dist/fonts/create-google-font-url.d.ts +2 -0
  38. package/dist/fonts/create-google-font-url.js +27 -0
  39. package/dist/fonts/create-google-font-url.js.map +1 -0
  40. package/dist/fonts/google-font-familiy.d.cts +1 -0
  41. package/dist/fonts/google-font-familiy.d.ts +1 -0
  42. package/dist/fonts/google-font.cjs +42 -0
  43. package/dist/fonts/google-font.cjs.map +1 -0
  44. package/dist/fonts/google-font.d.cts +4 -0
  45. package/dist/fonts/google-font.d.ts +4 -0
  46. package/dist/fonts/google-font.js +42 -0
  47. package/dist/fonts/google-font.js.map +1 -0
  48. package/dist/fonts/index.d.cts +4 -0
  49. package/dist/fonts/resolve-font-config.cjs +28 -0
  50. package/dist/fonts/resolve-font-config.cjs.map +1 -0
  51. package/dist/fonts/resolve-font-config.js +28 -0
  52. package/dist/fonts/resolve-font-config.js.map +1 -0
  53. package/dist/fonts/resolve-font-stylesheets.cjs +47 -0
  54. package/dist/fonts/resolve-font-stylesheets.cjs.map +1 -0
  55. package/dist/fonts/resolve-font-stylesheets.js +47 -0
  56. package/dist/fonts/resolve-font-stylesheets.js.map +1 -0
  57. package/dist/fonts/types.d.cts +28 -0
  58. package/dist/fonts/types.d.ts +28 -0
  59. package/dist/fonts/typography.cjs +172 -0
  60. package/dist/fonts/typography.cjs.map +1 -0
  61. package/dist/fonts/typography.d.cts +2 -0
  62. package/dist/fonts/typography.d.ts +2 -0
  63. package/dist/fonts/typography.js +170 -0
  64. package/dist/fonts/typography.js.map +1 -0
  65. package/dist/global.css +135 -0
  66. package/dist/index.cjs +9 -0
  67. package/dist/index.d.cts +10 -0
  68. package/dist/index.d.ts +9 -0
  69. package/dist/index.js +5 -0
  70. package/dist/scope-context.cjs +58 -0
  71. package/dist/scope-context.cjs.map +1 -0
  72. package/dist/scope-context.d.cts +14 -0
  73. package/dist/scope-context.d.ts +14 -0
  74. package/dist/scope-context.js +56 -0
  75. package/dist/scope-context.js.map +1 -0
  76. package/dist/theme-scopes.css +90 -0
  77. package/dist/theme.cjs +56 -0
  78. package/dist/theme.cjs.map +1 -0
  79. package/dist/theme.css +194 -0
  80. package/dist/theme.d.cts +18 -0
  81. package/dist/theme.d.ts +17 -0
  82. package/dist/theme.js +56 -0
  83. package/dist/theme.js.map +1 -0
  84. package/dist/types.d.cts +185 -0
  85. package/dist/types.d.ts +185 -0
  86. package/package.json +73 -4
  87. package/README.md +0 -3
@@ -0,0 +1,172 @@
1
+ // src/fonts/typography.ts
2
+ const typographyDefaults = {
3
+ display1: {
4
+ size: 80,
5
+ lineHeight: 1.05,
6
+ weight: 300,
7
+ letterSpacing: -1.5,
8
+ font: "heading",
9
+ responsive: {
10
+ min: 40,
11
+ max: 80,
12
+ minViewport: 360,
13
+ maxViewport: 1440
14
+ }
15
+ },
16
+ display2: {
17
+ size: 60,
18
+ lineHeight: 1.1,
19
+ weight: 300,
20
+ letterSpacing: -.5,
21
+ font: "heading",
22
+ responsive: {
23
+ min: 36,
24
+ max: 60,
25
+ minViewport: 360,
26
+ maxViewport: 1200
27
+ }
28
+ },
29
+ headline1: {
30
+ size: 48,
31
+ lineHeight: 1.15,
32
+ weight: 400,
33
+ letterSpacing: -.5,
34
+ font: "heading",
35
+ responsive: {
36
+ min: 32,
37
+ max: 48,
38
+ minViewport: 360,
39
+ maxViewport: 1200
40
+ }
41
+ },
42
+ headline2: {
43
+ size: 36,
44
+ lineHeight: 1.2,
45
+ weight: 400,
46
+ letterSpacing: -.25,
47
+ font: "heading",
48
+ responsive: {
49
+ min: 28,
50
+ max: 36,
51
+ minViewport: 360,
52
+ maxViewport: 1024
53
+ }
54
+ },
55
+ headline3: {
56
+ size: 28,
57
+ lineHeight: 1.25,
58
+ weight: 400,
59
+ letterSpacing: 0,
60
+ font: "heading",
61
+ responsive: {
62
+ min: 22,
63
+ max: 28,
64
+ minViewport: 360,
65
+ maxViewport: 900
66
+ }
67
+ },
68
+ headline4: {
69
+ size: 20,
70
+ lineHeight: 1.3,
71
+ weight: 500,
72
+ letterSpacing: .15,
73
+ font: "heading"
74
+ },
75
+ subtitle1: {
76
+ size: 16,
77
+ lineHeight: 1.5,
78
+ weight: 500,
79
+ letterSpacing: .15,
80
+ font: "heading"
81
+ },
82
+ subtitle2: {
83
+ size: 14,
84
+ lineHeight: 1.43,
85
+ weight: 500,
86
+ letterSpacing: .1,
87
+ font: "heading"
88
+ },
89
+ body1: {
90
+ size: 16,
91
+ lineHeight: 1.5,
92
+ weight: 400,
93
+ letterSpacing: .5,
94
+ font: "body"
95
+ },
96
+ body2: {
97
+ size: 14,
98
+ lineHeight: 1.43,
99
+ weight: 400,
100
+ letterSpacing: .25,
101
+ font: "body"
102
+ },
103
+ button: {
104
+ size: 14,
105
+ lineHeight: 1.43,
106
+ weight: 500,
107
+ letterSpacing: .5,
108
+ font: "body"
109
+ },
110
+ caption: {
111
+ size: 12,
112
+ lineHeight: 1.4,
113
+ weight: 400,
114
+ letterSpacing: .4,
115
+ font: "body"
116
+ },
117
+ overline: {
118
+ size: 10,
119
+ lineHeight: 1.6,
120
+ weight: 500,
121
+ letterSpacing: 1,
122
+ font: "body"
123
+ }
124
+ };
125
+ const createFluidFontSize = ({ min, max, minViewport = 360, maxViewport = 1440 }) => {
126
+ const minRem = min / 16;
127
+ const maxRem = max / 16;
128
+ const slope = (max - min) / (maxViewport - minViewport) * 100;
129
+ return `clamp(${minRem}rem, ${((min - slope * minViewport / 100) / 16).toFixed(4)}rem + ${slope.toFixed(4)}vw, ${maxRem}rem)`;
130
+ };
131
+ const fontSizeScaleByRole = {
132
+ headline4: "xl",
133
+ subtitle1: "base",
134
+ subtitle2: "sm",
135
+ body1: "base",
136
+ body2: "sm",
137
+ button: "sm",
138
+ caption: "xs"
139
+ };
140
+ const fontWeightTokenByValue = /* @__PURE__ */ new Map([
141
+ [400, "normal"],
142
+ [500, "medium"],
143
+ [600, "semibold"],
144
+ [700, "bold"],
145
+ [800, "extrabold"]
146
+ ]);
147
+ const lineHeightTokenByValue = /* @__PURE__ */ new Map([
148
+ [1, "none"],
149
+ [1.15, "tight"],
150
+ [1.3, "snug"],
151
+ [1.5, "normal"],
152
+ [1.625, "relaxed"],
153
+ [2, "loose"]
154
+ ]);
155
+ const createTypographyRole = (name, typography) => {
156
+ const fontSizeScale = fontSizeScaleByRole[name];
157
+ const fontWeightToken = fontWeightTokenByValue.get(typography.weight);
158
+ const lineHeightToken = lineHeightTokenByValue.get(typography.lineHeight);
159
+ return {
160
+ font: typography.font,
161
+ fontSize: fontSizeScale !== void 0 ? `var(--puzzle-font-size-${fontSizeScale})` : "responsive" in typography ? createFluidFontSize(typography.responsive) : `${typography.size / 16}rem`,
162
+ fontWeight: fontWeightToken !== void 0 ? `var(--puzzle-font-weight-${fontWeightToken})` : String(typography.weight),
163
+ lineHeight: lineHeightToken !== void 0 ? `var(--puzzle-font-line-height-${lineHeightToken})` : String(typography.lineHeight),
164
+ letterSpacing: `${typography.letterSpacing / typography.size}em`
165
+ };
166
+ };
167
+ const DEFAULT_TYPOGRAPHY_ROLES = Object.fromEntries(Object.entries(typographyDefaults).map(([name, typography]) => [name, createTypographyRole(name, typography)]));
168
+ exports.DEFAULT_TYPOGRAPHY_ROLES = DEFAULT_TYPOGRAPHY_ROLES;
169
+ exports.createFluidFontSize = createFluidFontSize;
170
+ exports.typographyDefaults = typographyDefaults;
171
+
172
+ //# sourceMappingURL=typography.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"typography.cjs","names":[],"sources":["../../src/fonts/typography.ts"],"sourcesContent":["import type { ThemeTypographyRoleTokens, TypographyStyle } from \"../types\";\n\nexport type { TypographyStyle } from \"../types\";\n\nexport const typographyDefaults = {\n display1: {\n size: 80,\n lineHeight: 1.05,\n weight: 300,\n letterSpacing: -1.5,\n font: \"heading\",\n responsive: {\n min: 40,\n max: 80,\n minViewport: 360,\n maxViewport: 1440,\n },\n },\n display2: {\n size: 60,\n lineHeight: 1.1,\n weight: 300,\n letterSpacing: -0.5,\n font: \"heading\",\n responsive: {\n min: 36,\n max: 60,\n minViewport: 360,\n maxViewport: 1200,\n },\n },\n headline1: {\n size: 48,\n lineHeight: 1.15,\n weight: 400,\n letterSpacing: -0.5,\n font: \"heading\",\n responsive: {\n min: 32,\n max: 48,\n minViewport: 360,\n maxViewport: 1200,\n },\n },\n headline2: {\n size: 36,\n lineHeight: 1.2,\n weight: 400,\n letterSpacing: -0.25,\n font: \"heading\",\n responsive: {\n min: 28,\n max: 36,\n minViewport: 360,\n maxViewport: 1024,\n },\n },\n headline3: {\n size: 28,\n lineHeight: 1.25,\n weight: 400,\n letterSpacing: 0,\n font: \"heading\",\n responsive: {\n min: 22,\n max: 28,\n minViewport: 360,\n maxViewport: 900,\n },\n },\n headline4: {\n size: 20,\n lineHeight: 1.3,\n weight: 500,\n letterSpacing: 0.15,\n font: \"heading\",\n },\n subtitle1: {\n size: 16,\n lineHeight: 1.5,\n weight: 500,\n letterSpacing: 0.15,\n font: \"heading\",\n },\n subtitle2: {\n size: 14,\n lineHeight: 1.43,\n weight: 500,\n letterSpacing: 0.1,\n font: \"heading\",\n },\n body1: {\n size: 16,\n lineHeight: 1.5,\n weight: 400,\n letterSpacing: 0.5,\n font: \"body\",\n },\n body2: {\n size: 14,\n lineHeight: 1.43,\n weight: 400,\n letterSpacing: 0.25,\n font: \"body\",\n },\n button: {\n size: 14,\n lineHeight: 1.43,\n weight: 500,\n letterSpacing: 0.5,\n font: \"body\",\n },\n caption: {\n size: 12,\n lineHeight: 1.4,\n weight: 400,\n letterSpacing: 0.4,\n font: \"body\",\n },\n overline: {\n size: 10,\n lineHeight: 1.6,\n weight: 500,\n letterSpacing: 1,\n font: \"body\",\n },\n} as const;\n\nexport type ResponsiveFontSize = {\n min: number;\n max: number;\n minViewport?: number;\n maxViewport?: number;\n};\n\nexport const createFluidFontSize = ({\n min,\n max,\n minViewport = 360,\n maxViewport = 1440,\n}: ResponsiveFontSize): string => {\n const minRem = min / 16;\n const maxRem = max / 16;\n\n const slope = ((max - min) / (maxViewport - minViewport)) * 100;\n const intercept = (min - (slope * minViewport) / 100) / 16;\n\n return `clamp(${minRem}rem, ${intercept.toFixed(4)}rem + ${slope.toFixed(4)}vw, ${maxRem}rem)`;\n};\n\nconst fontSizeScaleByRole: Partial<Record<TypographyStyle, string>> = {\n headline4: \"xl\",\n subtitle1: \"base\",\n subtitle2: \"sm\",\n body1: \"base\",\n body2: \"sm\",\n button: \"sm\",\n caption: \"xs\",\n};\n\nconst fontWeightTokenByValue = new Map<number, string>([\n [400, \"normal\"],\n [500, \"medium\"],\n [600, \"semibold\"],\n [700, \"bold\"],\n [800, \"extrabold\"],\n]);\n\nconst lineHeightTokenByValue = new Map<number, string>([\n [1, \"none\"],\n [1.15, \"tight\"],\n [1.3, \"snug\"],\n [1.5, \"normal\"],\n [1.625, \"relaxed\"],\n [2, \"loose\"],\n]);\n\nconst createTypographyRole = (\n name: TypographyStyle,\n typography: (typeof typographyDefaults)[TypographyStyle],\n): ThemeTypographyRoleTokens => {\n const fontSizeScale = fontSizeScaleByRole[name];\n const fontWeightToken = fontWeightTokenByValue.get(typography.weight);\n const lineHeightToken = lineHeightTokenByValue.get(typography.lineHeight);\n\n return {\n font: typography.font,\n\n fontSize:\n fontSizeScale !== undefined\n ? `var(--puzzle-font-size-${fontSizeScale})`\n : \"responsive\" in typography\n ? createFluidFontSize(typography.responsive)\n : `${typography.size / 16}rem`,\n\n fontWeight:\n fontWeightToken !== undefined\n ? `var(--puzzle-font-weight-${fontWeightToken})`\n : String(typography.weight),\n\n lineHeight:\n lineHeightToken !== undefined\n ? `var(--puzzle-font-line-height-${lineHeightToken})`\n : String(typography.lineHeight),\n\n letterSpacing: `${typography.letterSpacing / typography.size}em`,\n };\n};\n\nexport const DEFAULT_TYPOGRAPHY_ROLES = Object.fromEntries(\n Object.entries(typographyDefaults).map(([name, typography]) => [\n name,\n createTypographyRole(\n name as TypographyStyle,\n typography as (typeof typographyDefaults)[TypographyStyle],\n ),\n ]),\n) as Record<TypographyStyle, ThemeTypographyRoleTokens>;\n"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import { TypographyStyle } from "../types.cjs";
2
+ export type { TypographyStyle };
@@ -0,0 +1,2 @@
1
+ import { TypographyStyle } from "../types.js";
2
+ export type { TypographyStyle };
@@ -0,0 +1,170 @@
1
+ // src/fonts/typography.ts
2
+ const typographyDefaults = {
3
+ display1: {
4
+ size: 80,
5
+ lineHeight: 1.05,
6
+ weight: 300,
7
+ letterSpacing: -1.5,
8
+ font: "heading",
9
+ responsive: {
10
+ min: 40,
11
+ max: 80,
12
+ minViewport: 360,
13
+ maxViewport: 1440
14
+ }
15
+ },
16
+ display2: {
17
+ size: 60,
18
+ lineHeight: 1.1,
19
+ weight: 300,
20
+ letterSpacing: -.5,
21
+ font: "heading",
22
+ responsive: {
23
+ min: 36,
24
+ max: 60,
25
+ minViewport: 360,
26
+ maxViewport: 1200
27
+ }
28
+ },
29
+ headline1: {
30
+ size: 48,
31
+ lineHeight: 1.15,
32
+ weight: 400,
33
+ letterSpacing: -.5,
34
+ font: "heading",
35
+ responsive: {
36
+ min: 32,
37
+ max: 48,
38
+ minViewport: 360,
39
+ maxViewport: 1200
40
+ }
41
+ },
42
+ headline2: {
43
+ size: 36,
44
+ lineHeight: 1.2,
45
+ weight: 400,
46
+ letterSpacing: -.25,
47
+ font: "heading",
48
+ responsive: {
49
+ min: 28,
50
+ max: 36,
51
+ minViewport: 360,
52
+ maxViewport: 1024
53
+ }
54
+ },
55
+ headline3: {
56
+ size: 28,
57
+ lineHeight: 1.25,
58
+ weight: 400,
59
+ letterSpacing: 0,
60
+ font: "heading",
61
+ responsive: {
62
+ min: 22,
63
+ max: 28,
64
+ minViewport: 360,
65
+ maxViewport: 900
66
+ }
67
+ },
68
+ headline4: {
69
+ size: 20,
70
+ lineHeight: 1.3,
71
+ weight: 500,
72
+ letterSpacing: .15,
73
+ font: "heading"
74
+ },
75
+ subtitle1: {
76
+ size: 16,
77
+ lineHeight: 1.5,
78
+ weight: 500,
79
+ letterSpacing: .15,
80
+ font: "heading"
81
+ },
82
+ subtitle2: {
83
+ size: 14,
84
+ lineHeight: 1.43,
85
+ weight: 500,
86
+ letterSpacing: .1,
87
+ font: "heading"
88
+ },
89
+ body1: {
90
+ size: 16,
91
+ lineHeight: 1.5,
92
+ weight: 400,
93
+ letterSpacing: .5,
94
+ font: "body"
95
+ },
96
+ body2: {
97
+ size: 14,
98
+ lineHeight: 1.43,
99
+ weight: 400,
100
+ letterSpacing: .25,
101
+ font: "body"
102
+ },
103
+ button: {
104
+ size: 14,
105
+ lineHeight: 1.43,
106
+ weight: 500,
107
+ letterSpacing: .5,
108
+ font: "body"
109
+ },
110
+ caption: {
111
+ size: 12,
112
+ lineHeight: 1.4,
113
+ weight: 400,
114
+ letterSpacing: .4,
115
+ font: "body"
116
+ },
117
+ overline: {
118
+ size: 10,
119
+ lineHeight: 1.6,
120
+ weight: 500,
121
+ letterSpacing: 1,
122
+ font: "body"
123
+ }
124
+ };
125
+ const createFluidFontSize = ({ min, max, minViewport = 360, maxViewport = 1440 }) => {
126
+ const minRem = min / 16;
127
+ const maxRem = max / 16;
128
+ const slope = (max - min) / (maxViewport - minViewport) * 100;
129
+ return `clamp(${minRem}rem, ${((min - slope * minViewport / 100) / 16).toFixed(4)}rem + ${slope.toFixed(4)}vw, ${maxRem}rem)`;
130
+ };
131
+ const fontSizeScaleByRole = {
132
+ headline4: "xl",
133
+ subtitle1: "base",
134
+ subtitle2: "sm",
135
+ body1: "base",
136
+ body2: "sm",
137
+ button: "sm",
138
+ caption: "xs"
139
+ };
140
+ const fontWeightTokenByValue = /* @__PURE__ */ new Map([
141
+ [400, "normal"],
142
+ [500, "medium"],
143
+ [600, "semibold"],
144
+ [700, "bold"],
145
+ [800, "extrabold"]
146
+ ]);
147
+ const lineHeightTokenByValue = /* @__PURE__ */ new Map([
148
+ [1, "none"],
149
+ [1.15, "tight"],
150
+ [1.3, "snug"],
151
+ [1.5, "normal"],
152
+ [1.625, "relaxed"],
153
+ [2, "loose"]
154
+ ]);
155
+ const createTypographyRole = (name, typography) => {
156
+ const fontSizeScale = fontSizeScaleByRole[name];
157
+ const fontWeightToken = fontWeightTokenByValue.get(typography.weight);
158
+ const lineHeightToken = lineHeightTokenByValue.get(typography.lineHeight);
159
+ return {
160
+ font: typography.font,
161
+ fontSize: fontSizeScale !== void 0 ? `var(--puzzle-font-size-${fontSizeScale})` : "responsive" in typography ? createFluidFontSize(typography.responsive) : `${typography.size / 16}rem`,
162
+ fontWeight: fontWeightToken !== void 0 ? `var(--puzzle-font-weight-${fontWeightToken})` : String(typography.weight),
163
+ lineHeight: lineHeightToken !== void 0 ? `var(--puzzle-font-line-height-${lineHeightToken})` : String(typography.lineHeight),
164
+ letterSpacing: `${typography.letterSpacing / typography.size}em`
165
+ };
166
+ };
167
+ const DEFAULT_TYPOGRAPHY_ROLES = Object.fromEntries(Object.entries(typographyDefaults).map(([name, typography]) => [name, createTypographyRole(name, typography)]));
168
+ export { DEFAULT_TYPOGRAPHY_ROLES, createFluidFontSize, typographyDefaults };
169
+
170
+ //# sourceMappingURL=typography.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"typography.js","names":[],"sources":["../../src/fonts/typography.ts"],"sourcesContent":["import type { ThemeTypographyRoleTokens, TypographyStyle } from \"../types\";\n\nexport type { TypographyStyle } from \"../types\";\n\nexport const typographyDefaults = {\n display1: {\n size: 80,\n lineHeight: 1.05,\n weight: 300,\n letterSpacing: -1.5,\n font: \"heading\",\n responsive: {\n min: 40,\n max: 80,\n minViewport: 360,\n maxViewport: 1440,\n },\n },\n display2: {\n size: 60,\n lineHeight: 1.1,\n weight: 300,\n letterSpacing: -0.5,\n font: \"heading\",\n responsive: {\n min: 36,\n max: 60,\n minViewport: 360,\n maxViewport: 1200,\n },\n },\n headline1: {\n size: 48,\n lineHeight: 1.15,\n weight: 400,\n letterSpacing: -0.5,\n font: \"heading\",\n responsive: {\n min: 32,\n max: 48,\n minViewport: 360,\n maxViewport: 1200,\n },\n },\n headline2: {\n size: 36,\n lineHeight: 1.2,\n weight: 400,\n letterSpacing: -0.25,\n font: \"heading\",\n responsive: {\n min: 28,\n max: 36,\n minViewport: 360,\n maxViewport: 1024,\n },\n },\n headline3: {\n size: 28,\n lineHeight: 1.25,\n weight: 400,\n letterSpacing: 0,\n font: \"heading\",\n responsive: {\n min: 22,\n max: 28,\n minViewport: 360,\n maxViewport: 900,\n },\n },\n headline4: {\n size: 20,\n lineHeight: 1.3,\n weight: 500,\n letterSpacing: 0.15,\n font: \"heading\",\n },\n subtitle1: {\n size: 16,\n lineHeight: 1.5,\n weight: 500,\n letterSpacing: 0.15,\n font: \"heading\",\n },\n subtitle2: {\n size: 14,\n lineHeight: 1.43,\n weight: 500,\n letterSpacing: 0.1,\n font: \"heading\",\n },\n body1: {\n size: 16,\n lineHeight: 1.5,\n weight: 400,\n letterSpacing: 0.5,\n font: \"body\",\n },\n body2: {\n size: 14,\n lineHeight: 1.43,\n weight: 400,\n letterSpacing: 0.25,\n font: \"body\",\n },\n button: {\n size: 14,\n lineHeight: 1.43,\n weight: 500,\n letterSpacing: 0.5,\n font: \"body\",\n },\n caption: {\n size: 12,\n lineHeight: 1.4,\n weight: 400,\n letterSpacing: 0.4,\n font: \"body\",\n },\n overline: {\n size: 10,\n lineHeight: 1.6,\n weight: 500,\n letterSpacing: 1,\n font: \"body\",\n },\n} as const;\n\nexport type ResponsiveFontSize = {\n min: number;\n max: number;\n minViewport?: number;\n maxViewport?: number;\n};\n\nexport const createFluidFontSize = ({\n min,\n max,\n minViewport = 360,\n maxViewport = 1440,\n}: ResponsiveFontSize): string => {\n const minRem = min / 16;\n const maxRem = max / 16;\n\n const slope = ((max - min) / (maxViewport - minViewport)) * 100;\n const intercept = (min - (slope * minViewport) / 100) / 16;\n\n return `clamp(${minRem}rem, ${intercept.toFixed(4)}rem + ${slope.toFixed(4)}vw, ${maxRem}rem)`;\n};\n\nconst fontSizeScaleByRole: Partial<Record<TypographyStyle, string>> = {\n headline4: \"xl\",\n subtitle1: \"base\",\n subtitle2: \"sm\",\n body1: \"base\",\n body2: \"sm\",\n button: \"sm\",\n caption: \"xs\",\n};\n\nconst fontWeightTokenByValue = new Map<number, string>([\n [400, \"normal\"],\n [500, \"medium\"],\n [600, \"semibold\"],\n [700, \"bold\"],\n [800, \"extrabold\"],\n]);\n\nconst lineHeightTokenByValue = new Map<number, string>([\n [1, \"none\"],\n [1.15, \"tight\"],\n [1.3, \"snug\"],\n [1.5, \"normal\"],\n [1.625, \"relaxed\"],\n [2, \"loose\"],\n]);\n\nconst createTypographyRole = (\n name: TypographyStyle,\n typography: (typeof typographyDefaults)[TypographyStyle],\n): ThemeTypographyRoleTokens => {\n const fontSizeScale = fontSizeScaleByRole[name];\n const fontWeightToken = fontWeightTokenByValue.get(typography.weight);\n const lineHeightToken = lineHeightTokenByValue.get(typography.lineHeight);\n\n return {\n font: typography.font,\n\n fontSize:\n fontSizeScale !== undefined\n ? `var(--puzzle-font-size-${fontSizeScale})`\n : \"responsive\" in typography\n ? createFluidFontSize(typography.responsive)\n : `${typography.size / 16}rem`,\n\n fontWeight:\n fontWeightToken !== undefined\n ? `var(--puzzle-font-weight-${fontWeightToken})`\n : String(typography.weight),\n\n lineHeight:\n lineHeightToken !== undefined\n ? `var(--puzzle-font-line-height-${lineHeightToken})`\n : String(typography.lineHeight),\n\n letterSpacing: `${typography.letterSpacing / typography.size}em`,\n };\n};\n\nexport const DEFAULT_TYPOGRAPHY_ROLES = Object.fromEntries(\n Object.entries(typographyDefaults).map(([name, typography]) => [\n name,\n createTypographyRole(\n name as TypographyStyle,\n typography as (typeof typographyDefaults)[TypographyStyle],\n ),\n ]),\n) as Record<TypographyStyle, ThemeTypographyRoleTokens>;\n"],"mappings":"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"}
@@ -0,0 +1,135 @@
1
+ :root:has(style[data-puzzle-global-styles]) *, :root:has(style[data-puzzle-global-styles]) :before, :root:has(style[data-puzzle-global-styles]) :after {
2
+ box-sizing: border-box;
3
+ }
4
+
5
+ :root:has(style[data-puzzle-global-styles]) {
6
+ color-scheme: light;
7
+ }
8
+
9
+ :root:has(style[data-puzzle-global-styles]) body {
10
+ -webkit-text-size-adjust: 100%;
11
+ text-size-adjust: 100%;
12
+ color: var(--puzzle-color-text, #171717);
13
+ background: var(--puzzle-color-background, #f7f4ea);
14
+ font-family: var(--puzzle-font-family-body1, system-ui, sans-serif);
15
+ font-size: var(--puzzle-font-size-body1, 1rem);
16
+ font-weight: var(--puzzle-font-weight-body1, 400);
17
+ line-height: var(--puzzle-font-line-height-body1, 1.5);
18
+ letter-spacing: var(--puzzle-font-letter-spacing-body1, 0);
19
+ margin: 0;
20
+ }
21
+
22
+ :root:has(style[data-puzzle-global-styles]) :where(input, textarea, select, button) {
23
+ font: inherit;
24
+ }
25
+
26
+ :root:has(style[data-puzzle-global-styles]) :where(button) {
27
+ cursor: pointer;
28
+ font-family: var(--puzzle-font-family-button, inherit);
29
+ font-size: var(--puzzle-font-size-button, inherit);
30
+ font-weight: var(--puzzle-font-weight-button, inherit);
31
+ line-height: var(--puzzle-font-line-height-button, inherit);
32
+ letter-spacing: var(--puzzle-font-letter-spacing-button, inherit);
33
+ }
34
+
35
+ :root:has(style[data-puzzle-global-styles]) :where(button:disabled, input:disabled, textarea:disabled, select:disabled) {
36
+ cursor: not-allowed;
37
+ }
38
+
39
+ :root:has(style[data-puzzle-global-styles]) :where(h1, h2, h3, h4, p) {
40
+ margin-block: 0;
41
+ }
42
+
43
+ :root:has(style[data-puzzle-global-styles]) :where(h1) {
44
+ font-family: var(--puzzle-font-family-headline1, inherit);
45
+ font-size: var(--puzzle-font-size-headline1, 2.25rem);
46
+ font-weight: var(--puzzle-font-weight-headline1, 700);
47
+ line-height: var(--puzzle-font-line-height-headline1, 1.15);
48
+ letter-spacing: var(--puzzle-font-letter-spacing-headline1, -.025em);
49
+ }
50
+
51
+ :root:has(style[data-puzzle-global-styles]) :where(h2) {
52
+ font-family: var(--puzzle-font-family-headline2, inherit);
53
+ font-size: var(--puzzle-font-size-headline2, 1.875rem);
54
+ font-weight: var(--puzzle-font-weight-headline2, 700);
55
+ line-height: var(--puzzle-font-line-height-headline2, 1.2);
56
+ letter-spacing: var(--puzzle-font-letter-spacing-headline2, -.025em);
57
+ }
58
+
59
+ :root:has(style[data-puzzle-global-styles]) :where(h3) {
60
+ font-family: var(--puzzle-font-family-headline3, inherit);
61
+ font-size: var(--puzzle-font-size-headline3, 1.5rem);
62
+ font-weight: var(--puzzle-font-weight-headline3, 600);
63
+ line-height: var(--puzzle-font-line-height-headline3, 1.3);
64
+ letter-spacing: var(--puzzle-font-letter-spacing-headline3, 0);
65
+ }
66
+
67
+ :root:has(style[data-puzzle-global-styles]) :where(h4) {
68
+ font-family: var(--puzzle-font-family-headline4, inherit);
69
+ font-size: var(--puzzle-font-size-headline4, 1.25rem);
70
+ font-weight: var(--puzzle-font-weight-headline4, 600);
71
+ line-height: var(--puzzle-font-line-height-headline4, 1.3);
72
+ letter-spacing: var(--puzzle-font-letter-spacing-headline4, 0);
73
+ }
74
+
75
+ :root:has(style[data-puzzle-global-styles]) :where(h1, h2, h3, h4) + :where(h1, h2, h3, h4) {
76
+ margin-block-start: var(--puzzle-font-gap-heading-stack-gap, .3em);
77
+ }
78
+
79
+ :root:has(style[data-puzzle-global-styles]) :where(h1, h2, h3, h4) + :where(p) {
80
+ margin-block-start: var(--puzzle-font-gap-heading-paragraph-gap, .65em);
81
+ }
82
+
83
+ :root:has(style[data-puzzle-global-styles]) :where(p) + :where(p) {
84
+ margin-block-start: var(--puzzle-font-gap-paragraph-gap, 1em);
85
+ }
86
+
87
+ :root:has(style[data-puzzle-global-styles]) :where(p) + :where(h1, h2, h3, h4) {
88
+ margin-block-start: var(--puzzle-font-gap-section-gap, 1.5em);
89
+ }
90
+
91
+ :where(:root:has(style[data-puzzle-global-styles])) :where(a) {
92
+ color: var(--puzzle-color-primary, #2563eb);
93
+ }
94
+
95
+ :root:has(style[data-puzzle-global-styles]) :where(:focus-visible) {
96
+ outline: 2px solid var(--puzzle-color-ring, #2563eb);
97
+ outline-offset: 2px;
98
+ }
99
+
100
+ @media (prefers-reduced-motion: reduce) {
101
+ :root:has(style[data-puzzle-global-styles]) *, :root:has(style[data-puzzle-global-styles]) :before, :root:has(style[data-puzzle-global-styles]) :after {
102
+ scroll-behavior: auto !important;
103
+ transition-duration: .01ms !important;
104
+ animation-duration: .01ms !important;
105
+ animation-iteration-count: 1 !important;
106
+ }
107
+ }
108
+
109
+ @media (forced-colors: active) {
110
+ :root:has(style[data-puzzle-global-styles]) :where(:focus-visible) {
111
+ outline-offset: 2px;
112
+ outline: 2px solid highlight;
113
+ }
114
+
115
+ :root:has(style[data-puzzle-global-styles]) :where(a) {
116
+ color: linktext;
117
+ }
118
+
119
+ :root:has(style[data-puzzle-global-styles]) :where(button, input, textarea, select, [role="button"], [role="option"]) {
120
+ forced-color-adjust: auto;
121
+ }
122
+
123
+ :root:has(style[data-puzzle-global-styles]) :where(input, textarea, select) {
124
+ border-color: buttontext;
125
+ }
126
+
127
+ :root:has(style[data-puzzle-global-styles]) :where(button:disabled, input:disabled, textarea:disabled, select:disabled) {
128
+ color: graytext;
129
+ border-color: graytext;
130
+ }
131
+
132
+ :root:has(style[data-puzzle-global-styles]) :where([aria-invalid="true"], [data-invalid="true"]) {
133
+ outline-color: mark;
134
+ }
135
+ }
package/dist/index.cjs ADDED
@@ -0,0 +1,9 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_create_google_font_url = require("./fonts/create-google-font-url.cjs");
3
+ const require_google_font = require("./fonts/google-font.cjs");
4
+ const require_theme = require("./theme.cjs");
5
+ const require_breakpoints = require("./breakpoints.cjs");
6
+ exports.BREAKPOINTS = require_breakpoints.BREAKPOINTS;
7
+ exports.GoogleFont = require_google_font.GoogleFont;
8
+ exports.Theme = require_theme.Theme;
9
+ exports.createGoogleFontUrl = require_create_google_font_url.createGoogleFontUrl;
@@ -0,0 +1,10 @@
1
+ import { FontConfig, FontDisplay, FontRole, FontStyle, FontStylesheet, ResolvedFontConfig, ThemeFonts } from "./fonts/types.cjs";
2
+ import { createGoogleFontUrl } from "./fonts/create-google-font-url.cjs";
3
+ import { GoogleFont } from "./fonts/google-font.cjs";
4
+ import "./fonts/index.cjs";
5
+ import { Theme, ThemeProps, ThemeScope } from "./theme.cjs";
6
+ import "./fonts/typography.cjs";
7
+ import { BREAKPOINTS, Breakpoint } from "./breakpoints.cjs";
8
+ import { ColorTheme, ThemeColorSchemeTokens, ThemeMode, ThemeTokenOverrides, ThemeTokens, ThemeTypographyFontRole, ThemeTypographyRoleTokens, TypographyStyle } from "./types.cjs";
9
+ import { ThemeComponents, ThemeImageComponent, ThemeLinkComponent, ThemeLinkComponentConfig } from "./components.types.cjs";
10
+ export { BREAKPOINTS, type Breakpoint, type ColorTheme, type FontConfig, type FontDisplay, type FontRole, type FontStyle, type FontStylesheet, GoogleFont, type ResolvedFontConfig, Theme, type ThemeColorSchemeTokens, type ThemeComponents, type ThemeFonts, type ThemeImageComponent, type ThemeLinkComponent, type ThemeLinkComponentConfig, type ThemeMode, type ThemeProps, type ThemeScope, type ThemeTokenOverrides, type ThemeTokens, type ThemeTypographyFontRole, type ThemeTypographyRoleTokens, type TypographyStyle, createGoogleFontUrl };
@@ -0,0 +1,9 @@
1
+ import { createGoogleFontUrl } from "./fonts/create-google-font-url.js";
2
+ import { GoogleFont } from "./fonts/google-font.js";
3
+ import { FontConfig, FontDisplay, FontRole, FontStyle, FontStylesheet, ResolvedFontConfig, ThemeFonts } from "./fonts/types.js";
4
+ import { Theme, ThemeProps, ThemeScope } from "./theme.js";
5
+ import "./fonts/typography.js";
6
+ import { BREAKPOINTS, Breakpoint } from "./breakpoints.js";
7
+ import { ColorTheme, ThemeColorSchemeTokens, ThemeMode, ThemeTokenOverrides, ThemeTokens, ThemeTypographyFontRole, ThemeTypographyRoleTokens, TypographyStyle } from "./types.js";
8
+ import { ThemeComponents, ThemeImageComponent, ThemeLinkComponent, ThemeLinkComponentConfig } from "./components.types.js";
9
+ export { BREAKPOINTS, type Breakpoint, type ColorTheme, type FontConfig, type FontDisplay, type FontRole, type FontStyle, type FontStylesheet, GoogleFont, type ResolvedFontConfig, Theme, type ThemeColorSchemeTokens, type ThemeComponents, type ThemeFonts, type ThemeImageComponent, type ThemeLinkComponent, type ThemeLinkComponentConfig, type ThemeMode, type ThemeProps, type ThemeScope, type ThemeTokenOverrides, type ThemeTokens, type ThemeTypographyFontRole, type ThemeTypographyRoleTokens, type TypographyStyle, createGoogleFontUrl };
package/dist/index.js ADDED
@@ -0,0 +1,5 @@
1
+ import { createGoogleFontUrl } from "./fonts/create-google-font-url.js";
2
+ import { GoogleFont } from "./fonts/google-font.js";
3
+ import { Theme } from "./theme.js";
4
+ import { BREAKPOINTS } from "./breakpoints.js";
5
+ export { BREAKPOINTS, GoogleFont, Theme, createGoogleFontUrl };
@@ -0,0 +1,58 @@
1
+ "use client";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ let react_jsx_runtime = require("react/jsx-runtime");
4
+ let react = require("react");
5
+ // src/scope-context.tsx
6
+ const ThemeScopeContext = (0, react.createContext)(null);
7
+ const ThemeScopeProvider = ({ scopeId, theme, children }) => {
8
+ const scopeElementRef = (0, react.useRef)(null);
9
+ const [portalState, setPortalState] = (0, react.useState)(null);
10
+ (0, react.useEffect)(() => {
11
+ if (scopeId === null) return;
12
+ const ownerDocument = scopeElementRef.current?.ownerDocument;
13
+ if (!ownerDocument?.body) return;
14
+ const portalTarget = ownerDocument.createElement("div");
15
+ portalTarget.className = "puzzle-theme-scope puzzle-theme-scope--portal";
16
+ portalTarget.dataset.puzzleThemeScope = scopeId;
17
+ portalTarget.dataset.theme = theme;
18
+ portalTarget.dataset.puzzleThemePortal = "true";
19
+ ownerDocument.body.append(portalTarget);
20
+ setPortalState({
21
+ scopeId,
22
+ theme,
23
+ element: portalTarget
24
+ });
25
+ return () => {
26
+ portalTarget.remove();
27
+ };
28
+ }, [scopeId, theme]);
29
+ const portalTarget = scopeId !== null && portalState?.scopeId === scopeId && portalState.theme === theme ? portalState.element : null;
30
+ const value = (0, react.useMemo)(() => {
31
+ return scopeId === null ? null : {
32
+ scopeId,
33
+ theme,
34
+ portalTarget
35
+ };
36
+ }, [
37
+ scopeId,
38
+ theme,
39
+ portalTarget
40
+ ]);
41
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ThemeScopeContext.Provider, {
42
+ value,
43
+ children: scopeId === null ? children : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
44
+ ref: scopeElementRef,
45
+ className: "puzzle-theme-scope",
46
+ "data-puzzle-theme-scope": scopeId,
47
+ "data-theme": theme,
48
+ children
49
+ })
50
+ });
51
+ };
52
+ const useThemeScope = () => {
53
+ return (0, react.useContext)(ThemeScopeContext);
54
+ };
55
+ exports.ThemeScopeProvider = ThemeScopeProvider;
56
+ exports.useThemeScope = useThemeScope;
57
+
58
+ //# sourceMappingURL=scope-context.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scope-context.cjs","names":["createContext","useRef","useState","useMemo","useContext"],"sources":["../src/scope-context.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n createContext,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n type PropsWithChildren,\n} from \"react\";\n\nimport type { ThemeMode } from \"./types\";\n\ntype ThemeScopeContextValue = {\n scopeId: string;\n theme: ThemeMode;\n portalTarget: HTMLDivElement | null;\n};\n\ntype ThemeScopePortalState = {\n scopeId: string;\n theme: ThemeMode;\n element: HTMLDivElement;\n};\n\ntype ThemeScopeProviderProps = PropsWithChildren<{\n scopeId: string | null;\n theme: ThemeMode;\n}>;\n\nconst ThemeScopeContext = createContext<ThemeScopeContextValue | null>(null);\n\nconst ThemeScopeProvider = ({\n scopeId,\n theme,\n children,\n}: ThemeScopeProviderProps) => {\n const scopeElementRef = useRef<HTMLDivElement>(null);\n const [portalState, setPortalState] = useState<ThemeScopePortalState | null>(\n null,\n );\n\n useEffect(() => {\n if (scopeId === null) {\n return;\n }\n\n const ownerDocument = scopeElementRef.current?.ownerDocument;\n\n if (!ownerDocument?.body) {\n return;\n }\n\n const portalTarget = ownerDocument.createElement(\"div\");\n\n portalTarget.className = \"puzzle-theme-scope puzzle-theme-scope--portal\";\n portalTarget.dataset.puzzleThemeScope = scopeId;\n portalTarget.dataset.theme = theme;\n portalTarget.dataset.puzzleThemePortal = \"true\";\n\n ownerDocument.body.append(portalTarget);\n\n setPortalState({\n scopeId,\n theme,\n element: portalTarget,\n });\n\n return () => {\n portalTarget.remove();\n };\n }, [scopeId, theme]);\n\n const portalTarget =\n scopeId !== null &&\n portalState?.scopeId === scopeId &&\n portalState.theme === theme\n ? portalState.element\n : null;\n\n const value = useMemo<ThemeScopeContextValue | null>(() => {\n return scopeId === null\n ? null\n : {\n scopeId,\n theme,\n portalTarget,\n };\n }, [scopeId, theme, portalTarget]);\n\n return (\n <ThemeScopeContext.Provider value={value}>\n {scopeId === null ? (\n children\n ) : (\n <div\n ref={scopeElementRef}\n className=\"puzzle-theme-scope\"\n data-puzzle-theme-scope={scopeId}\n data-theme={theme}\n >\n {children}\n </div>\n )}\n </ThemeScopeContext.Provider>\n );\n};\n\nconst useThemeScope = () => {\n return useContext(ThemeScopeContext);\n};\n\nexport { ThemeScopeProvider, useThemeScope, type ThemeScopeContextValue };\n"],"mappings":";;;;;AA+BA,MAAM,qBAAA,GAAoBA,MAAAA,cAAAA,CAA6C,IAAI;AAE3E,MAAM,sBAAsB,EAC1B,SACA,OACA,eAC6B;CAC7B,MAAM,mBAAA,GAAkBC,MAAAA,OAAAA,CAAuB,IAAI;CACnD,MAAM,CAAC,aAAa,mBAAA,GAAkBC,MAAAA,SAAAA,CACpC,IACF;CAEA,CAAA,GAAA,MAAA,UAAA,OAAgB;EACd,IAAI,YAAY,MACd;EAGF,MAAM,gBAAgB,gBAAgB,SAAS;EAE/C,IAAI,CAAC,eAAe,MAClB;EAGF,MAAM,eAAe,cAAc,cAAc,KAAK;EAEtD,aAAa,YAAY;EACzB,aAAa,QAAQ,mBAAmB;EACxC,aAAa,QAAQ,QAAQ;EAC7B,aAAa,QAAQ,oBAAoB;EAEzC,cAAc,KAAK,OAAO,YAAY;EAEtC,eAAe;GACb;GACA;GACA,SAAS;EACX,CAAC;EAED,aAAa;GACX,aAAa,OAAO;EACtB;CACF,GAAG,CAAC,SAAS,KAAK,CAAC;CAEnB,MAAM,eACJ,YAAY,QACZ,aAAa,YAAY,WACzB,YAAY,UAAU,QAClB,YAAY,UACZ;CAEN,MAAM,SAAA,GAAQC,MAAAA,QAAAA,OAA6C;EACzD,OAAO,YAAY,OACf,OACA;GACE;GACA;GACA;EACF;CACN,GAAG;EAAC;EAAS;EAAO;CAAY,CAAC;CAEjC,OACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,kBAAkB,UAAnB;EAAmC;EAChC,UAAA,YAAY,OACX,WAEA,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;GACE,KAAK;GACL,WAAU;GACV,2BAAyB;GACzB,cAAY;GAEX;EACE,CAAA;CAEmB,CAAA;AAEhC;AAEA,MAAM,sBAAsB;CAC1B,QAAA,GAAOC,MAAAA,WAAAA,CAAW,iBAAiB;AACrC"}
@@ -0,0 +1,14 @@
1
+ import { ThemeMode } from "./types.cjs";
2
+ import { PropsWithChildren } from "react";
3
+ type ThemeScopeContextValue = {
4
+ scopeId: string;
5
+ theme: ThemeMode;
6
+ portalTarget: HTMLDivElement | null;
7
+ };
8
+ type ThemeScopeProviderProps = PropsWithChildren<{
9
+ scopeId: string | null;
10
+ theme: ThemeMode;
11
+ }>;
12
+ declare const ThemeScopeProvider: ({ scopeId, theme, children }: ThemeScopeProviderProps) => import("react").JSX.Element;
13
+ declare const useThemeScope: () => ThemeScopeContextValue | null;
14
+ export { type ThemeScopeContextValue, ThemeScopeProvider, useThemeScope };
@@ -0,0 +1,14 @@
1
+ import { ThemeMode } from "./types.js";
2
+ import { PropsWithChildren } from "react";
3
+ type ThemeScopeContextValue = {
4
+ scopeId: string;
5
+ theme: ThemeMode;
6
+ portalTarget: HTMLDivElement | null;
7
+ };
8
+ type ThemeScopeProviderProps = PropsWithChildren<{
9
+ scopeId: string | null;
10
+ theme: ThemeMode;
11
+ }>;
12
+ declare const ThemeScopeProvider: ({ scopeId, theme, children }: ThemeScopeProviderProps) => import("react").JSX.Element;
13
+ declare const useThemeScope: () => ThemeScopeContextValue | null;
14
+ export { type ThemeScopeContextValue, ThemeScopeProvider, useThemeScope };