m3-svelte 6.0.3 → 7.0.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 (59) hide show
  1. package/package/buttons/Button.svelte +39 -33
  2. package/package/buttons/Button.svelte.d.ts +7 -5
  3. package/package/buttons/ConnectedButtons.svelte +0 -6
  4. package/package/buttons/FAB.svelte +1 -4
  5. package/package/buttons/SplitButton.svelte +3 -6
  6. package/package/containers/Card.svelte +4 -6
  7. package/package/containers/ListItem.svelte +25 -20
  8. package/package/containers/ListItem.svelte.d.ts +7 -6
  9. package/package/containers/MenuItem.svelte +3 -4
  10. package/package/containers/Snackbar.svelte +2 -5
  11. package/package/etc/colors.d.ts +13 -0
  12. package/package/{misc → etc}/colors.js +36 -23
  13. package/package/etc/layer.css +38 -0
  14. package/package/etc/layer.d.ts +1 -0
  15. package/package/etc/layer.js +142 -0
  16. package/package/etc/recommended-styles.css +8 -0
  17. package/package/{misc → etc}/styles.css +75 -47
  18. package/package/{misc → etc}/tailwind-styles.css +0 -2
  19. package/package/etc/unocss-preset.d.ts +3 -0
  20. package/package/etc/unocss-preset.js +85 -0
  21. package/package/forms/Checkbox.svelte +1 -3
  22. package/package/forms/Chip.svelte +22 -14
  23. package/package/forms/Chip.svelte.d.ts +5 -2
  24. package/package/forms/DateField.svelte +9 -13
  25. package/package/forms/DateFieldOutlined.svelte +9 -13
  26. package/package/forms/RadioAnim1.svelte +1 -3
  27. package/package/forms/RadioAnim2.svelte +1 -3
  28. package/package/forms/RadioAnim3.svelte +1 -3
  29. package/package/forms/Select.svelte +4 -7
  30. package/package/forms/SelectOutlined.svelte +2 -5
  31. package/package/forms/Slider.svelte +1 -1
  32. package/package/forms/TextField.svelte +2 -5
  33. package/package/forms/TextFieldMultiline.svelte +2 -3
  34. package/package/forms/TextFieldOutlined.svelte +2 -5
  35. package/package/forms/TextFieldOutlinedMultiline.svelte +2 -3
  36. package/package/forms/_picker/FocusPicker.svelte +1 -4
  37. package/package/forms/_picker/Header.svelte +28 -33
  38. package/package/forms/_picker/Item.svelte +1 -12
  39. package/package/index.d.ts +3 -7
  40. package/package/index.js +3 -7
  41. package/package/misc/animation.js +5 -1
  42. package/package/misc/badge.js +1 -1
  43. package/package/misc/easing.js +4 -3
  44. package/package/misc/typing-utils.d.ts +14 -5
  45. package/package/nav/NavCMLXItem.svelte +7 -10
  46. package/package/nav/NavCMLXItem.svelte.d.ts +2 -2
  47. package/package/nav/Tabs.svelte +1 -4
  48. package/package/nav/TabsLink.svelte +7 -4
  49. package/package/nav/VariableTabs.svelte +1 -4
  50. package/package/nav/VariableTabsLink.svelte +1 -3
  51. package/package.json +38 -19
  52. package/package/buttons/TogglePrimitive.svelte +0 -22
  53. package/package/buttons/TogglePrimitive.svelte.d.ts +0 -11
  54. package/package/misc/Layer.svelte +0 -213
  55. package/package/misc/Layer.svelte.d.ts +0 -3
  56. package/package/misc/colors.d.ts +0 -4
  57. package/package/misc/recommended-styles.css +0 -41
  58. package/package/misc/utils.d.ts +0 -6
  59. package/package/misc/utils.js +0 -39
@@ -1,12 +1,15 @@
1
1
  <script lang="ts">
2
- import type { HTMLButtonAttributes, HTMLAttributes } from "svelte/elements";
2
+ import type { HTMLButtonAttributes, HTMLAttributes, HTMLLabelAttributes } from "svelte/elements";
3
3
  import type { Snippet } from "svelte";
4
- import type { LabelAttrs, AnchorAttrs } from "../misc/typing-utils";
5
- import Layer from "../misc/Layer.svelte";
4
+ import type { AnchorAttrs, NotLink } from "../misc/typing-utils";
5
+ import "../etc/layer.js";
6
6
 
7
7
  // If you want a toggle button, use `for` with a checkbox input.
8
- type SummaryAttrs = HTMLAttributes<HTMLElement> & { summary: true };
9
- type ActionProps = LabelAttrs | AnchorAttrs | SummaryAttrs | HTMLButtonAttributes;
8
+ type ActionProps =
9
+ | AnchorAttrs
10
+ | (NotLink<HTMLLabelAttributes> & { label: true })
11
+ | (NotLink<HTMLAttributes<HTMLElement>> & { summary: true })
12
+ | NotLink<HTMLButtonAttributes>;
10
13
  type Props = {
11
14
  variant?: "elevated" | "filled" | "tonal" | "outlined" | "text";
12
15
  square?: boolean;
@@ -25,30 +28,27 @@
25
28
  }: Props = $props();
26
29
  </script>
27
30
 
28
- {#if "for" in props}
29
- <label class="m3-container {variant} {size} icon-{iconType}" class:square {...props}>
30
- <Layer />
31
- {@render children()}
32
- </label>
33
- {:else if "href" in props}
34
- <a class="m3-container {variant} {size} icon-{iconType}" class:square {...props}>
35
- <Layer />
31
+ {#if props.href != undefined}
32
+ <a class="m3-container m3-layer {variant} {size} icon-{iconType}" class:square {...props}>
36
33
  {@render children()}
37
34
  </a>
35
+ {:else if "label" in props}
36
+ {@const { label: _, ...extra } = props}
37
+ <label class="m3-container m3-layer {variant} {size} icon-{iconType}" class:square {...extra}>
38
+ {@render children()}
39
+ </label>
38
40
  {:else if "summary" in props}
39
41
  {@const { summary: _, ...extra } = props}
40
- <summary class="m3-container {variant} {size} icon-{iconType}" class:square {...extra}>
41
- <Layer />
42
+ <summary class="m3-container m3-layer {variant} {size} icon-{iconType}" class:square {...extra}>
42
43
  {@render children()}
43
44
  </summary>
44
45
  {:else}
45
46
  <button
46
- type={"onclick" in props ? "button" : "submit"}
47
- class="m3-container {variant} {size} icon-{iconType}"
47
+ type={props.onclick ? "button" : "submit"}
48
+ class="m3-container m3-layer {variant} {size} icon-{iconType}"
48
49
  class:square
49
50
  {...props}
50
51
  >
51
- <Layer />
52
52
  {@render children()}
53
53
  </button>
54
54
  {/if}
@@ -168,20 +168,19 @@
168
168
  background-color: transparent;
169
169
  cursor: pointer;
170
170
  user-select: none;
171
- position: relative;
172
171
 
173
172
  &:disabled,
174
- &:is(:global(input:disabled) + label) {
173
+ &:has(> :global(input:disabled)) {
175
174
  background-color: --translucent(var(--m3c-on-surface), 0.12);
176
175
  color: --translucent(var(--m3c-on-surface), 0.38);
177
176
  cursor: auto;
178
177
  }
179
178
 
180
- &.elevated:not(:disabled, :global(input:disabled) + label) {
179
+ &.elevated:not(:disabled, :has(> :global(input:disabled))) {
181
180
  background-color: var(--m3c-surface-container-low);
182
181
  color: var(--m3c-primary);
183
182
  box-shadow: var(--m3-elevation-1);
184
- &:is(:global(input:checked) + .m3-container) {
183
+ &:has(> :global(input:checked)) {
185
184
  background-color: var(--m3c-primary);
186
185
  color: var(--m3c-on-primary);
187
186
  }
@@ -191,18 +190,18 @@
191
190
  }
192
191
  }
193
192
  }
194
- &.filled:not(:disabled, :global(input:disabled) + label) {
193
+ &.filled:not(:disabled, :has(> :global(input:disabled))) {
195
194
  background-color: var(--m3c-primary);
196
195
  color: var(--m3c-on-primary);
197
- &:is(:global(input:is([type="checkbox"], [type="radio"]):not(:checked)) + label) {
196
+ &:has(> :global(input:is([type="checkbox"], [type="radio"]):not(:checked))) {
198
197
  background-color: var(--m3c-surface-container);
199
198
  color: var(--m3c-on-surface-variant);
200
199
  }
201
200
  }
202
- &.tonal:not(:disabled, :global(input:disabled) + label) {
201
+ &.tonal:not(:disabled, :has(> :global(input:disabled))) {
203
202
  background-color: var(--m3c-secondary-container);
204
203
  color: var(--m3c-on-secondary-container);
205
- &:is(:global(input:checked) + label) {
204
+ &:has(> :global(input:checked)) {
206
205
  background-color: var(--m3c-secondary);
207
206
  color: var(--m3c-on-secondary);
208
207
  }
@@ -219,20 +218,20 @@
219
218
  outline-width: 3px;
220
219
  outline-offset: -3px;
221
220
  }
222
- &.outlined:not(:disabled, :global(input:disabled) + label) {
221
+ &.outlined:not(:disabled, :has(> :global(input:disabled))) {
223
222
  outline-color: var(--m3c-outline-variant);
224
223
  color: var(--m3c-on-surface-variant);
225
- &:is(:global(input:checked) + label) {
224
+ &:has(> :global(input:checked)) {
226
225
  outline-color: var(--m3c-inverse-surface);
227
226
  background-color: var(--m3c-inverse-surface);
228
227
  color: var(--m3c-inverse-on-surface);
229
228
  }
230
229
  }
231
- &.outlined:is(:disabled, :global(input:disabled) + label) {
230
+ &.outlined:has(> :global(input:disabled)) {
232
231
  outline-color: --translucent(var(--m3c-on-surface), 0.12);
233
232
  background-color: transparent;
234
233
  }
235
- &.text:not(:disabled, :global(input:disabled) + label) {
234
+ &.text:not(:disabled, :has(> :global(input:disabled))) {
236
235
  color: var(--m3c-primary);
237
236
  }
238
237
  @media (hover: hover) {
@@ -241,11 +240,11 @@
241
240
  }
242
241
  }
243
242
 
244
- &.square:not(:global(input:checked) + label, :global(:open) > summary),
245
- &:not(.square):is(:global(input:checked) + label, :global(:open) > summary) {
243
+ &.square:not(:has(> :global(input:checked)), :global(:open) > summary),
244
+ &:not(.square):is(:has(> :global(input:checked)), :global(:open) > summary) {
246
245
  border-radius: var(--square-shape);
247
246
  }
248
- &:active:not(:disabled, :global(input:disabled) + label) {
247
+ &:active:not(:disabled, :has(> :global(input:disabled))) {
249
248
  border-radius: var(--pressed-shape) !important;
250
249
  }
251
250
  }
@@ -257,6 +256,13 @@
257
256
  width: 1.25rem;
258
257
  height: 1.25rem;
259
258
  }
259
+ .m3-container > :global(input) {
260
+ position: absolute;
261
+ opacity: 0;
262
+ width: 0;
263
+ height: 0;
264
+ pointer-events: none;
265
+ }
260
266
 
261
267
  .m3-container {
262
268
  print-color-adjust: exact;
@@ -1,10 +1,12 @@
1
- import type { HTMLButtonAttributes, HTMLAttributes } from "svelte/elements";
1
+ import type { HTMLButtonAttributes, HTMLAttributes, HTMLLabelAttributes } from "svelte/elements";
2
2
  import type { Snippet } from "svelte";
3
- import type { LabelAttrs, AnchorAttrs } from "../misc/typing-utils";
4
- type SummaryAttrs = HTMLAttributes<HTMLElement> & {
3
+ import type { AnchorAttrs, NotLink } from "../misc/typing-utils";
4
+ import "../etc/layer.js";
5
+ type ActionProps = AnchorAttrs | (NotLink<HTMLLabelAttributes> & {
6
+ label: true;
7
+ }) | (NotLink<HTMLAttributes<HTMLElement>> & {
5
8
  summary: true;
6
- };
7
- type ActionProps = LabelAttrs | AnchorAttrs | SummaryAttrs | HTMLButtonAttributes;
9
+ }) | NotLink<HTMLButtonAttributes>;
8
10
  type Props = {
9
11
  variant?: "elevated" | "filled" | "tonal" | "outlined" | "text";
10
12
  square?: boolean;
@@ -16,11 +16,5 @@
16
16
  gap: 0.125rem;
17
17
  border-radius: var(--m3-shape-full);
18
18
  overflow: hidden;
19
-
20
- > :global(input) {
21
- position: absolute;
22
- opacity: 0;
23
- pointer-events: none;
24
- }
25
19
  }
26
20
  </style>
@@ -1,7 +1,6 @@
1
1
  <script lang="ts">
2
2
  import type { IconifyIcon } from "@iconify/types";
3
3
  import Icon from "../misc/Icon.svelte";
4
- import Layer from "../misc/Layer.svelte";
5
4
  import type { ButtonAttrs } from "../misc/typing-utils";
6
5
 
7
6
  type ContentProps =
@@ -38,10 +37,9 @@
38
37
 
39
38
  <button
40
39
  type="button"
41
- class="m3-container color-{color} size-{size} elevation-{elevation}"
40
+ class="m3-container color-{color} size-{size} elevation-{elevation} m3-layer"
42
41
  {...extra}
43
42
  >
44
- <Layer />
45
43
  {#if icon}
46
44
  <Icon {icon} />
47
45
  {/if}
@@ -62,7 +60,6 @@
62
60
  @apply --m3-label-large;
63
61
  display: inline-flex;
64
62
  border: none;
65
- position: relative;
66
63
  overflow: hidden;
67
64
 
68
65
  align-items: center;
@@ -1,7 +1,6 @@
1
1
  <script lang="ts">
2
2
  import iconExpand from "@ktibow/iconset-material-symbols/keyboard-arrow-down";
3
3
  import type { Snippet } from "svelte";
4
- import Layer from "../misc/Layer.svelte";
5
4
  import Icon from "../misc/Icon.svelte";
6
5
  import type { ButtonAttrs } from "../misc/typing-utils";
7
6
 
@@ -36,13 +35,11 @@
36
35
  </script>
37
36
 
38
37
  <div class="m3-container {variant}">
39
- <button type="button" class="split" {...extra}>
40
- <Layer />
38
+ <button type="button" class="split m3-layer" {...extra}>
41
39
  {@render children()}
42
40
  </button>
43
41
  <details class="align-{x} align-{y}" use:autoclose>
44
- <summary class="split">
45
- <Layer />
42
+ <summary class="split m3-layer">
46
43
  <Icon icon={iconExpand} size={22} />
47
44
  </summary>
48
45
  {@render menu()}
@@ -146,7 +143,7 @@
146
143
  }
147
144
  &:is(details[open] summary) {
148
145
  --inner-shape: var(--m3-split-button-outer-shape);
149
- > :global(.tint) {
146
+ &::after {
150
147
  opacity: 0.08;
151
148
  }
152
149
  > :global(svg) {
@@ -1,6 +1,5 @@
1
1
  <script lang="ts">
2
2
  import type { Snippet } from "svelte";
3
- import Layer from "../misc/Layer.svelte";
4
3
  import type { ButtonAttrs, DivAttrs } from "../misc/typing-utils";
5
4
 
6
5
  type ActionProps = ButtonAttrs | DivAttrs;
@@ -15,9 +14,8 @@
15
14
  } & ActionProps = $props();
16
15
  </script>
17
16
 
18
- {#if "onclick" in extra}
19
- <button type="button" class="m3-container {variant}" {...extra}>
20
- <Layer />
17
+ {#if extra.onclick}
18
+ <button type="button" class="m3-container {variant} m3-layer" {...extra}>
21
19
  {@render children()}
22
20
  </button>
23
21
  {:else}
@@ -36,7 +34,6 @@
36
34
  .m3-container {
37
35
  display: flex;
38
36
  flex-direction: column;
39
- position: relative;
40
37
  padding: 1rem; /* protip: use margin: -1rem (adjust as needed) to make images stretch to the end */
41
38
  border: none;
42
39
  border-radius: var(--m3-card-shape);
@@ -50,12 +47,13 @@
50
47
  font: inherit;
51
48
  letter-spacing: inherit;
52
49
  cursor: pointer;
50
+ transition: box-shadow var(--m3-easing-fast);
53
51
  }
54
52
  @media (hover: hover) {
55
53
  button:hover {
56
54
  box-shadow: var(--m3-elevation-1);
57
55
  }
58
- button.type-elevated:hover {
56
+ button.elevated:hover {
59
57
  box-shadow: var(--m3-elevation-2);
60
58
  }
61
59
  }
@@ -1,14 +1,21 @@
1
1
  <script lang="ts">
2
2
  import type { Snippet } from "svelte";
3
- import type { HTMLAnchorAttributes, HTMLLabelAttributes } from "svelte/elements";
4
- import Layer from "../misc/Layer.svelte";
5
- import type { ButtonAttrs, DivAttrs, NotButton } from "../misc/typing-utils";
3
+ import type { HTMLLabelAttributes } from "svelte/elements";
6
4
 
5
+ import type {
6
+ ButtonAttrs,
7
+ AnchorAttrs,
8
+ DivAttrs,
9
+ NotButton,
10
+ NotLink,
11
+ } from "../misc/typing-utils";
12
+
13
+ type NotLabel<T> = T & { label?: false };
7
14
  type ActionProps =
8
- | DivAttrs
9
- | ButtonAttrs
10
- | ({ label: true } & NotButton<HTMLLabelAttributes>)
11
- | ({ href: string } & NotButton<HTMLAnchorAttributes>);
15
+ | NotLabel<ButtonAttrs>
16
+ | NotLabel<AnchorAttrs>
17
+ | (NotLink<NotButton<HTMLLabelAttributes>> & { label: true })
18
+ | NotLabel<DivAttrs>;
12
19
 
13
20
  let {
14
21
  leading,
@@ -54,22 +61,19 @@
54
61
  {/snippet}
55
62
 
56
63
  <li style:display="contents">
57
- {#if "label" in props}
58
- {@const { label: _, ...extra } = props}
59
- <label class="m3-container focus-inset lines-{lines}" {...extra}>
60
- <Layer />
61
- {@render content()}
62
- </label>
63
- {:else if "onclick" in props}
64
- <button type="button" class="m3-container focus-inset lines-{lines}" {...props}>
65
- <Layer />
64
+ {#if props.onclick}
65
+ <button type="button" class="m3-container m3-layer lines-{lines}" {...props}>
66
66
  {@render content()}
67
67
  </button>
68
- {:else if "href" in props}
69
- <a class="m3-container focus-inset lines-{lines}" {...props}>
70
- <Layer />
68
+ {:else if props.href != undefined}
69
+ <a class="m3-container m3-layer lines-{lines}" {...props}>
71
70
  {@render content()}
72
71
  </a>
72
+ {:else if props.label}
73
+ {@const { label: _, ...extra } = props}
74
+ <label class="m3-container m3-layer lines-{lines}" {...extra}>
75
+ {@render content()}
76
+ </label>
73
77
  {:else}
74
78
  <div class="m3-container lines-{lines}" {...props}>
75
79
  {@render content()}
@@ -79,6 +83,7 @@
79
83
 
80
84
  <style>
81
85
  .m3-container {
86
+ @apply --m3-focus-inward;
82
87
  display: flex;
83
88
  justify-self: stretch;
84
89
  padding: 0.5rem 1.5rem 0.5rem 1rem;
@@ -87,7 +92,7 @@
87
92
 
88
93
  text-align: inherit;
89
94
  border: none;
90
- position: relative;
95
+
91
96
  background: transparent;
92
97
  color: inherit;
93
98
  }
@@ -1,11 +1,12 @@
1
1
  import type { Snippet } from "svelte";
2
- import type { HTMLAnchorAttributes, HTMLLabelAttributes } from "svelte/elements";
3
- import type { ButtonAttrs, DivAttrs, NotButton } from "../misc/typing-utils";
4
- type ActionProps = DivAttrs | ButtonAttrs | ({
2
+ import type { HTMLLabelAttributes } from "svelte/elements";
3
+ import type { ButtonAttrs, AnchorAttrs, DivAttrs, NotButton, NotLink } from "../misc/typing-utils";
4
+ type NotLabel<T> = T & {
5
+ label?: false;
6
+ };
7
+ type ActionProps = NotLabel<ButtonAttrs> | NotLabel<AnchorAttrs> | (NotLink<NotButton<HTMLLabelAttributes>> & {
5
8
  label: true;
6
- } & NotButton<HTMLLabelAttributes>) | ({
7
- href: string;
8
- } & NotButton<HTMLAnchorAttributes>);
9
+ }) | NotLabel<DivAttrs>;
9
10
  type $$ComponentProps = {
10
11
  leading?: Snippet;
11
12
  overline?: string;
@@ -2,7 +2,6 @@
2
2
  import type { Snippet } from "svelte";
3
3
  import type { IconifyIcon } from "@iconify/types";
4
4
  import Icon from "../misc/Icon.svelte";
5
- import Layer from "../misc/Layer.svelte";
6
5
 
7
6
  let {
8
7
  icon,
@@ -17,8 +16,7 @@
17
16
  } = $props();
18
17
  </script>
19
18
 
20
- <button type="button" class="item focus-inset" {disabled} {onclick}>
21
- <Layer />
19
+ <button type="button" class="item m3-layer" {disabled} {onclick}>
22
20
  {#if icon == "space"}
23
21
  <span class="icon"></span>
24
22
  {:else if icon}
@@ -32,6 +30,7 @@
32
30
  <style>
33
31
  .item {
34
32
  @apply --m3-label-large;
33
+ @apply --m3-focus-inward;
35
34
  display: flex;
36
35
  align-items: center;
37
36
  height: --m3-density(3rem);
@@ -40,7 +39,7 @@
40
39
  white-space: nowrap;
41
40
 
42
41
  border: none;
43
- position: relative;
42
+
44
43
  background-color: transparent;
45
44
  color: var(--m3c-on-surface);
46
45
 
@@ -21,7 +21,6 @@
21
21
  import iconX from "@ktibow/iconset-material-symbols/close";
22
22
  import Icon from "../misc/Icon.svelte";
23
23
  import SnackbarItem from "./SnackbarItem.svelte";
24
- import Layer from "../misc/Layer.svelte";
25
24
 
26
25
  let { closeTitle = "Close" }: { closeTitle?: string } = $props();
27
26
  let shown:
@@ -61,13 +60,12 @@
61
60
  {#if shown.closable}
62
61
  <button
63
62
  type="button"
64
- class="close"
63
+ class="close m3-layer"
65
64
  title={closeTitle}
66
65
  onclick={() => {
67
66
  shown = undefined;
68
67
  }}
69
68
  >
70
- <Layer />
71
69
  <Icon icon={iconX} />
72
70
  </button>
73
71
  {/if}
@@ -80,7 +78,7 @@
80
78
  .holder {
81
79
  position: fixed;
82
80
  padding-bottom: 1rem;
83
- bottom: var(--m3v-bottom-offset);
81
+ bottom: var(--m3v-bottom-offset, 0);
84
82
  left: 50%;
85
83
  transform: translate(-50%, 0);
86
84
  z-index: 3;
@@ -100,7 +98,6 @@
100
98
  background-color: transparent;
101
99
  color: unset;
102
100
  cursor: pointer;
103
- position: relative;
104
101
  }
105
102
  button :global(svg) {
106
103
  width: 1.5rem;
@@ -0,0 +1,13 @@
1
+ import { MaterialDynamicColors, DynamicColor } from "@ktibow/material-color-utilities-nightly";
2
+ import type { DynamicScheme } from "@ktibow/material-color-utilities-nightly";
3
+ export declare const materialColors: MaterialDynamicColors;
4
+ export declare const primaryContainerSubtle: DynamicColor;
5
+ export declare const onPrimaryContainerSubtle: DynamicColor;
6
+ export declare const secondaryContainerSubtle: DynamicColor;
7
+ export declare const onSecondaryContainerSubtle: DynamicColor;
8
+ export declare const tertiaryContainerSubtle: DynamicColor;
9
+ export declare const onTertiaryContainerSubtle: DynamicColor;
10
+ export declare const errorContainerSubtle: DynamicColor;
11
+ export declare const onErrorContainerSubtle: DynamicColor;
12
+ export declare const colors: DynamicColor[];
13
+ export declare const genCSS: (light: DynamicScheme, dark: DynamicScheme, cs: DynamicColor[]) => string;
@@ -8,60 +8,60 @@ const onOnPrimary = DynamicColor.fromPalette({
8
8
  contrastCurve: () => new ContrastCurve(6, 6, 7, 11),
9
9
  });
10
10
  // Custom colors for you to use
11
- const primaryContainerSubtle = DynamicColor.fromPalette({
11
+ export const primaryContainerSubtle = DynamicColor.fromPalette({
12
12
  name: "primary_container_subtle",
13
13
  palette: (s) => s.primaryPalette,
14
14
  isBackground: true,
15
15
  background: (s) => materialColors.highestSurface(s),
16
16
  contrastCurve: () => undefined,
17
17
  });
18
- const onPrimaryContainerSubtle = DynamicColor.fromPalette({
18
+ export const onPrimaryContainerSubtle = DynamicColor.fromPalette({
19
19
  name: "on_primary_container_subtle",
20
20
  palette: (s) => s.primaryPalette,
21
21
  background: () => primaryContainerSubtle,
22
22
  contrastCurve: () => new ContrastCurve(6, 6, 7, 11),
23
23
  });
24
- const secondaryContainerSubtle = DynamicColor.fromPalette({
24
+ export const secondaryContainerSubtle = DynamicColor.fromPalette({
25
25
  name: "secondary_container_subtle",
26
26
  palette: (s) => s.secondaryPalette,
27
27
  isBackground: true,
28
28
  background: (s) => materialColors.highestSurface(s),
29
29
  contrastCurve: () => undefined,
30
30
  });
31
- const onSecondaryContainerSubtle = DynamicColor.fromPalette({
31
+ export const onSecondaryContainerSubtle = DynamicColor.fromPalette({
32
32
  name: "on_secondary_container_subtle",
33
33
  palette: (s) => s.secondaryPalette,
34
34
  background: () => secondaryContainerSubtle,
35
35
  contrastCurve: () => new ContrastCurve(6, 6, 7, 11),
36
36
  });
37
- const tertiaryContainerSubtle = DynamicColor.fromPalette({
37
+ export const tertiaryContainerSubtle = DynamicColor.fromPalette({
38
38
  name: "tertiary_container_subtle",
39
39
  palette: (s) => s.tertiaryPalette,
40
40
  isBackground: true,
41
41
  background: (s) => materialColors.highestSurface(s),
42
42
  contrastCurve: () => undefined,
43
43
  });
44
- const onTertiaryContainerSubtle = DynamicColor.fromPalette({
44
+ export const onTertiaryContainerSubtle = DynamicColor.fromPalette({
45
45
  name: "on_tertiary_container_subtle",
46
46
  palette: (s) => s.tertiaryPalette,
47
47
  background: () => tertiaryContainerSubtle,
48
48
  contrastCurve: () => new ContrastCurve(6, 6, 7, 11),
49
49
  });
50
- const errorContainerSubtle = DynamicColor.fromPalette({
50
+ export const errorContainerSubtle = DynamicColor.fromPalette({
51
51
  name: "error_container_subtle",
52
52
  palette: (s) => s.errorPalette,
53
53
  isBackground: true,
54
54
  background: (s) => materialColors.highestSurface(s),
55
55
  contrastCurve: () => undefined,
56
56
  });
57
- const onErrorContainerSubtle = DynamicColor.fromPalette({
57
+ export const onErrorContainerSubtle = DynamicColor.fromPalette({
58
58
  name: "on_error_container_subtle",
59
59
  palette: (s) => s.errorPalette,
60
60
  background: () => errorContainerSubtle,
61
61
  contrastCurve: () => new ContrastCurve(6, 6, 7, 11),
62
62
  });
63
63
  export const colors = [
64
- ...materialColors.allColors,
64
+ ...materialColors.allColors.filter((c) => c.name != "background" && c.name != "on_background"),
65
65
  materialColors.shadow(),
66
66
  materialColors.scrim(),
67
67
  onOnPrimary,
@@ -74,17 +74,30 @@ export const colors = [
74
74
  errorContainerSubtle,
75
75
  onErrorContainerSubtle,
76
76
  ];
77
- export const pairs = [
78
- [materialColors.primary(), materialColors.onPrimary()],
79
- [materialColors.primaryContainer(), materialColors.onPrimaryContainer()],
80
- [materialColors.secondary(), materialColors.onSecondary()],
81
- [materialColors.secondaryContainer(), materialColors.onSecondaryContainer()],
82
- [materialColors.tertiary(), materialColors.onTertiary()],
83
- [materialColors.tertiaryContainer(), materialColors.onTertiaryContainer()],
84
- [materialColors.background(), materialColors.onBackground()],
85
- [materialColors.surface(), materialColors.onSurface()],
86
- [materialColors.inverseSurface(), materialColors.inverseOnSurface()],
87
- [materialColors.surfaceVariant(), materialColors.onSurfaceVariant()],
88
- [materialColors.error(), materialColors.onError()],
89
- [materialColors.errorContainer(), materialColors.onErrorContainer()],
90
- ];
77
+ export const genCSS = (light, dark, cs) => {
78
+ const argbToHex = (argb) => {
79
+ const rgb = argb & 0xffffff;
80
+ const hex = rgb.toString(16).padStart(6, "0");
81
+ if (hex[0] == hex[1] && hex[2] == hex[3] && hex[4] == hex[5]) {
82
+ return `#${hex[0]}${hex[2]}${hex[4]}`;
83
+ }
84
+ return `#${hex}`;
85
+ };
86
+ const genColorVariable = (name, lightArgb, darkArgb) => {
87
+ const kebabCase = name.replaceAll("_", "-");
88
+ const lightHex = argbToHex(lightArgb);
89
+ const darkHex = argbToHex(darkArgb);
90
+ return ` --m3c-${kebabCase}: ${lightHex == darkHex ? lightHex : `light-dark(${lightHex}, ${darkHex})`};`;
91
+ };
92
+ const colors = cs
93
+ .map((color) => genColorVariable(color.name, color.getArgb(light), color.getArgb(dark)))
94
+ .join("\n");
95
+ return `:root {
96
+ color-scheme: light dark;
97
+ }
98
+ @layer tokens {
99
+ :root {
100
+ ${colors}
101
+ }
102
+ }`;
103
+ };
@@ -0,0 +1,38 @@
1
+ :where(.m3-layer) {
2
+ position: relative;
3
+
4
+ /* Hitbox for rounded elements */
5
+ &::before {
6
+ content: "";
7
+ position: absolute;
8
+ inset: 0;
9
+ }
10
+
11
+ /* Tint */
12
+ &::after {
13
+ content: "";
14
+ position: absolute;
15
+ inset: 0;
16
+ border-radius: inherit;
17
+ pointer-events: none;
18
+ background-color: currentColor;
19
+ opacity: 0;
20
+ transition: opacity var(--m3-easing-fast);
21
+ }
22
+ }
23
+ :disabled.m3-layer::after,
24
+ input:disabled + .m3-layer-container.m3-layer::after,
25
+ label:has(> input:disabled).m3-layer::after {
26
+ display: none;
27
+ }
28
+ @media (hover: hover) {
29
+ :hover.m3-layer::after,
30
+ :active.m3-layer::after {
31
+ opacity: 0.08;
32
+ }
33
+ }
34
+ :focus-visible.m3-layer::after,
35
+ label:has(> input:focus-visible).m3-layer::after,
36
+ html:not(.js) :active.m3-layer::after {
37
+ opacity: 0.12;
38
+ }
@@ -0,0 +1 @@
1
+ import "./layer.css";