@m3-baseui/react-tailwind 3.0.0 → 4.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 (64) hide show
  1. package/dist/components/badge/index.js +13 -1
  2. package/dist/components/badge/index.js.map +1 -1
  3. package/dist/components/bottom-app-bar/index.js +13 -1
  4. package/dist/components/bottom-app-bar/index.js.map +1 -1
  5. package/dist/components/bottom-sheet/index.js +13 -1
  6. package/dist/components/bottom-sheet/index.js.map +1 -1
  7. package/dist/components/button/index.d.ts +106 -1
  8. package/dist/components/button/index.js +168 -25
  9. package/dist/components/button/index.js.map +1 -1
  10. package/dist/components/button-group/index.js +13 -1
  11. package/dist/components/button-group/index.js.map +1 -1
  12. package/dist/components/card/index.js +13 -1
  13. package/dist/components/card/index.js.map +1 -1
  14. package/dist/components/carousel/index.js +13 -1
  15. package/dist/components/carousel/index.js.map +1 -1
  16. package/dist/components/date-picker/index.js +13 -1
  17. package/dist/components/date-picker/index.js.map +1 -1
  18. package/dist/components/dialog/index.js +13 -1
  19. package/dist/components/dialog/index.js.map +1 -1
  20. package/dist/components/fab-menu/index.js +13 -1
  21. package/dist/components/fab-menu/index.js.map +1 -1
  22. package/dist/components/item/index.d.ts +5 -5
  23. package/dist/components/item/index.js +13 -1
  24. package/dist/components/item/index.js.map +1 -1
  25. package/dist/components/list/index.js +13 -1
  26. package/dist/components/list/index.js.map +1 -1
  27. package/dist/components/loading-indicator/index.js +13 -1
  28. package/dist/components/loading-indicator/index.js.map +1 -1
  29. package/dist/components/menu/index.js +13 -1
  30. package/dist/components/menu/index.js.map +1 -1
  31. package/dist/components/navigation-drawer/index.js +13 -1
  32. package/dist/components/navigation-drawer/index.js.map +1 -1
  33. package/dist/components/navigation-rail/index.js +13 -1
  34. package/dist/components/navigation-rail/index.js.map +1 -1
  35. package/dist/components/search/index.js +13 -1
  36. package/dist/components/search/index.js.map +1 -1
  37. package/dist/components/segmented-button/index.js +13 -1
  38. package/dist/components/segmented-button/index.js.map +1 -1
  39. package/dist/components/select/index.js +13 -1
  40. package/dist/components/select/index.js.map +1 -1
  41. package/dist/components/side-sheet/index.js +13 -1
  42. package/dist/components/side-sheet/index.js.map +1 -1
  43. package/dist/components/slider/index.js +49 -15
  44. package/dist/components/slider/index.js.map +1 -1
  45. package/dist/components/snackbar/index.d.ts +5 -5
  46. package/dist/components/split-button/index.js +13 -1
  47. package/dist/components/split-button/index.js.map +1 -1
  48. package/dist/components/tabs/index.js +13 -1
  49. package/dist/components/tabs/index.js.map +1 -1
  50. package/dist/components/time-picker/index.js +13 -1
  51. package/dist/components/time-picker/index.js.map +1 -1
  52. package/dist/components/toolbar/index.js +13 -1
  53. package/dist/components/toolbar/index.js.map +1 -1
  54. package/dist/components/tooltip/index.js +13 -1
  55. package/dist/components/tooltip/index.js.map +1 -1
  56. package/dist/components/top-app-bar/index.js +13 -1
  57. package/dist/components/top-app-bar/index.js.map +1 -1
  58. package/dist/index.d.ts +1 -1
  59. package/dist/index.js +247 -111
  60. package/dist/index.js.map +1 -1
  61. package/dist/tv.d.ts +13 -8
  62. package/dist/tv.js +13 -1
  63. package/dist/tv.js.map +1 -1
  64. package/package.json +1 -1
@@ -20,12 +20,24 @@ var TYPESCALE = [
20
20
  "label-medium",
21
21
  "label-small"
22
22
  ];
23
+ var SHAPE = [
24
+ "none",
25
+ "extra-small",
26
+ "small",
27
+ "medium",
28
+ "large",
29
+ "large-increased",
30
+ "extra-large",
31
+ "extra-large-increased",
32
+ "full"
33
+ ];
23
34
  var tv = (options, config) => tv$1(options, {
24
35
  ...config,
25
36
  twMergeConfig: {
26
37
  extend: {
27
38
  classGroups: {
28
- "font-size": [{ text: [...TYPESCALE] }]
39
+ "font-size": [{ text: [...TYPESCALE] }],
40
+ rounded: [{ rounded: [...SHAPE] }]
29
41
  }
30
42
  }
31
43
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/tv.ts","../../../src/components/badge/badge.ts"],"names":["baseTv"],"mappings":";;;;;AAeA,IAAM,SAAA,GAAY;AAAA,EAChB,eAAA;AAAA,EACA,gBAAA;AAAA,EACA,eAAA;AAAA,EACA,gBAAA;AAAA,EACA,iBAAA;AAAA,EACA,gBAAA;AAAA,EACA,aAAA;AAAA,EACA,cAAA;AAAA,EACA,aAAA;AAAA,EACA,YAAA;AAAA,EACA,aAAA;AAAA,EACA,YAAA;AAAA,EACA,aAAA;AAAA,EACA,cAAA;AAAA,EACA;AACF,CAAA;AAEO,IAAM,EAAA,GAAS,CAAC,OAAA,EAAS,MAAA,KAC9BA,KAAO,OAAA,EAAS;AAAA,EACd,GAAG,MAAA;AAAA,EACH,aAAA,EAAe;AAAA,IACb,MAAA,EAAQ;AAAA,MACN,WAAA,EAAa;AAAA,QACX,WAAA,EAAa,CAAC,EAAE,IAAA,EAAM,CAAC,GAAG,SAAS,GAAG;AAAA;AACxC;AACF;AAEJ,CAAC,CAAA;;;ACjCI,IAAM,UAAU,EAAA,CAAG;AAAA,EACxB,IAAA,EAAM,gGAAA;AAAA,EACN,QAAA,EAAU;AAAA,IACR,IAAA,EAAM;AAAA,MACJ,KAAA,EAAO,8CAAA;AAAA,MACP,KAAA,EACE;AAAA;AACJ;AAEJ,CAAC;AAEM,IAAM,QAAQ,WAAA,CAAY;AAAA,EAC/B,IAAA,EAAM,CAAC,EAAE,IAAA,OAAW,OAAA,CAAQ,EAAE,MAAM;AACtC,CAAC","file":"index.js","sourcesContent":["/**\n * tv.ts — a tailwind-variants factory pre-configured for the M3 typescale.\n *\n * The Tailwind v4 preset exposes the 15 typescale roles as `text-<role>`\n * font-size utilities (e.g. `text-body-small`, `text-label-large`). Stock\n * tailwind-merge does not know these custom names, so it groups them with the\n * `text-<color>` utilities and drops one when a slot sets both a color *and* a\n * typescale (the common M3 case). That silently strips either the color or the\n * type, breaking token compliance.\n *\n * Teaching tailwind-merge that the typescale names belong to the `font-size`\n * group keeps color and type independent, so both survive the merge.\n */\nimport { type TV, tv as baseTv } from 'tailwind-variants';\n\nconst TYPESCALE = [\n 'display-large',\n 'display-medium',\n 'display-small',\n 'headline-large',\n 'headline-medium',\n 'headline-small',\n 'title-large',\n 'title-medium',\n 'title-small',\n 'body-large',\n 'body-medium',\n 'body-small',\n 'label-large',\n 'label-medium',\n 'label-small',\n] as const;\n\nexport const tv: TV = (options, config) =>\n baseTv(options, {\n ...config,\n twMergeConfig: {\n extend: {\n classGroups: {\n 'font-size': [{ text: [...TYPESCALE] }],\n },\n },\n },\n });\n","/**\n * badge.ts — tailwind-variants slots for the M3 Badge.\n *\n * error/on-error marker that anchors to the top-right of a positioned parent.\n * `small` is a 6dp dot; `large` is a 16dp pill carrying a `label-small` number.\n * Same DOM + `data-size` as the VE build.\n */\nimport { createBadge } from '@m3-baseui/core';\nimport { tv } from '../../tv';\n\nexport const badgeTv = tv({\n base: 'pointer-events-none select-none inline-flex items-center justify-center bg-error text-on-error',\n variants: {\n size: {\n small: 'absolute top-1 right-1 size-1.5 rounded-full',\n large:\n 'absolute -top-1 -right-1 min-w-4 h-4 px-1 rounded-full text-label-small leading-none tabular-nums',\n },\n },\n});\n\nexport const Badge = createBadge({\n root: ({ size }) => badgeTv({ size }),\n});\nexport type { BadgeProps, BadgeSize } from '@m3-baseui/core';\n"]}
1
+ {"version":3,"sources":["../../../src/tv.ts","../../../src/components/badge/badge.ts"],"names":["baseTv"],"mappings":";;;;;AAoBA,IAAM,SAAA,GAAY;AAAA,EAChB,eAAA;AAAA,EACA,gBAAA;AAAA,EACA,eAAA;AAAA,EACA,gBAAA;AAAA,EACA,iBAAA;AAAA,EACA,gBAAA;AAAA,EACA,aAAA;AAAA,EACA,cAAA;AAAA,EACA,aAAA;AAAA,EACA,YAAA;AAAA,EACA,aAAA;AAAA,EACA,YAAA;AAAA,EACA,aAAA;AAAA,EACA,cAAA;AAAA,EACA;AACF,CAAA;AAKA,IAAM,KAAA,GAAQ;AAAA,EACZ,MAAA;AAAA,EACA,aAAA;AAAA,EACA,OAAA;AAAA,EACA,QAAA;AAAA,EACA,OAAA;AAAA,EACA,iBAAA;AAAA,EACA,aAAA;AAAA,EACA,uBAAA;AAAA,EACA;AACF,CAAA;AAEO,IAAM,EAAA,GAAS,CAAC,OAAA,EAAS,MAAA,KAC9BA,KAAO,OAAA,EAAS;AAAA,EACd,GAAG,MAAA;AAAA,EACH,aAAA,EAAe;AAAA,IACb,MAAA,EAAQ;AAAA,MACN,WAAA,EAAa;AAAA,QACX,WAAA,EAAa,CAAC,EAAE,IAAA,EAAM,CAAC,GAAG,SAAS,GAAG,CAAA;AAAA,QACtC,OAAA,EAAS,CAAC,EAAE,OAAA,EAAS,CAAC,GAAG,KAAK,GAAG;AAAA;AACnC;AACF;AAEJ,CAAC,CAAA;;;ACtDI,IAAM,UAAU,EAAA,CAAG;AAAA,EACxB,IAAA,EAAM,gGAAA;AAAA,EACN,QAAA,EAAU;AAAA,IACR,IAAA,EAAM;AAAA,MACJ,KAAA,EAAO,8CAAA;AAAA,MACP,KAAA,EACE;AAAA;AACJ;AAEJ,CAAC;AAEM,IAAM,QAAQ,WAAA,CAAY;AAAA,EAC/B,IAAA,EAAM,CAAC,EAAE,IAAA,OAAW,OAAA,CAAQ,EAAE,MAAM;AACtC,CAAC","file":"index.js","sourcesContent":["/**\n * tv.ts — a tailwind-variants factory pre-configured for the M3 typescale and\n * shape scale.\n *\n * The Tailwind v4 preset exposes the 15 typescale roles as `text-<role>`\n * font-size utilities (e.g. `text-body-small`, `text-label-large`) and the\n * shape scale as `rounded-<role>` border-radius utilities (e.g. `rounded-small`,\n * `rounded-extra-large`). Stock tailwind-merge does not know these custom names,\n * so it (a) groups the typescale names with `text-<color>` and drops one when a\n * slot sets both a color *and* a typescale, and (b) fails to see two custom\n * `rounded-<role>` classes as conflicting, so a later corner override never\n * dedupes the resting one (both survive, and CSS source order — not intent —\n * decides). Either way token compliance / shape morph silently breaks.\n *\n * Teaching tailwind-merge that the typescale names belong to `font-size` and the\n * shape names belong to `rounded` keeps color and type independent and makes the\n * corner utilities override one another as expected.\n */\nimport { type TV, tv as baseTv } from 'tailwind-variants';\n\nconst TYPESCALE = [\n 'display-large',\n 'display-medium',\n 'display-small',\n 'headline-large',\n 'headline-medium',\n 'headline-small',\n 'title-large',\n 'title-medium',\n 'title-small',\n 'body-large',\n 'body-medium',\n 'body-small',\n 'label-large',\n 'label-medium',\n 'label-small',\n] as const;\n\n// M3 shape scale exposed as `rounded-<role>` (see @m3-baseui/tokens theme.css\n// `--radius-*`). `none` / `full` overlap stock Tailwind and are harmless to\n// re-list; the intermediate roles are what stock tailwind-merge misses.\nconst SHAPE = [\n 'none',\n 'extra-small',\n 'small',\n 'medium',\n 'large',\n 'large-increased',\n 'extra-large',\n 'extra-large-increased',\n 'full',\n] as const;\n\nexport const tv: TV = (options, config) =>\n baseTv(options, {\n ...config,\n twMergeConfig: {\n extend: {\n classGroups: {\n 'font-size': [{ text: [...TYPESCALE] }],\n rounded: [{ rounded: [...SHAPE] }],\n },\n },\n },\n });\n","/**\n * badge.ts — tailwind-variants slots for the M3 Badge.\n *\n * error/on-error marker that anchors to the top-right of a positioned parent.\n * `small` is a 6dp dot; `large` is a 16dp pill carrying a `label-small` number.\n * Same DOM + `data-size` as the VE build.\n */\nimport { createBadge } from '@m3-baseui/core';\nimport { tv } from '../../tv';\n\nexport const badgeTv = tv({\n base: 'pointer-events-none select-none inline-flex items-center justify-center bg-error text-on-error',\n variants: {\n size: {\n small: 'absolute top-1 right-1 size-1.5 rounded-full',\n large:\n 'absolute -top-1 -right-1 min-w-4 h-4 px-1 rounded-full text-label-small leading-none tabular-nums',\n },\n },\n});\n\nexport const Badge = createBadge({\n root: ({ size }) => badgeTv({ size }),\n});\nexport type { BadgeProps, BadgeSize } from '@m3-baseui/core';\n"]}
@@ -20,12 +20,24 @@ var TYPESCALE = [
20
20
  "label-medium",
21
21
  "label-small"
22
22
  ];
23
+ var SHAPE = [
24
+ "none",
25
+ "extra-small",
26
+ "small",
27
+ "medium",
28
+ "large",
29
+ "large-increased",
30
+ "extra-large",
31
+ "extra-large-increased",
32
+ "full"
33
+ ];
23
34
  var tv = (options, config) => tv$1(options, {
24
35
  ...config,
25
36
  twMergeConfig: {
26
37
  extend: {
27
38
  classGroups: {
28
- "font-size": [{ text: [...TYPESCALE] }]
39
+ "font-size": [{ text: [...TYPESCALE] }],
40
+ rounded: [{ rounded: [...SHAPE] }]
29
41
  }
30
42
  }
31
43
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/tv.ts","../../../src/components/bottom-app-bar/bottom-app-bar.ts"],"names":["baseTv"],"mappings":";;;;;AAeA,IAAM,SAAA,GAAY;AAAA,EAChB,eAAA;AAAA,EACA,gBAAA;AAAA,EACA,eAAA;AAAA,EACA,gBAAA;AAAA,EACA,iBAAA;AAAA,EACA,gBAAA;AAAA,EACA,aAAA;AAAA,EACA,cAAA;AAAA,EACA,aAAA;AAAA,EACA,YAAA;AAAA,EACA,aAAA;AAAA,EACA,YAAA;AAAA,EACA,aAAA;AAAA,EACA,cAAA;AAAA,EACA;AACF,CAAA;AAEO,IAAM,EAAA,GAAS,CAAC,OAAA,EAAS,MAAA,KAC9BA,KAAO,OAAA,EAAS;AAAA,EACd,GAAG,MAAA;AAAA,EACH,aAAA,EAAe;AAAA,IACb,MAAA,EAAQ;AAAA,MACN,WAAA,EAAa;AAAA,QACX,WAAA,EAAa,CAAC,EAAE,IAAA,EAAM,CAAC,GAAG,SAAS,GAAG;AAAA;AACxC;AACF;AAEJ,CAAC,CAAA;;;AClCI,IAAM,iBAAiB,EAAA,CAAG;AAAA,EAC/B,KAAA,EAAO;AAAA,IACL,IAAA,EAAM,4GAAA;AAAA,IACN,OAAA,EAAS,6CAAA;AAAA,IACT,GAAA,EAAK;AAAA;AAET,CAAC;AAED,IAAM,IAAI,cAAA,EAAe;AAClB,IAAM,eAAe,kBAAA,CAAmB;AAAA,EAC7C,IAAA,EAAM,EAAE,IAAA,EAAK;AAAA,EACb,OAAA,EAAS,EAAE,OAAA,EAAQ;AAAA,EACnB,GAAA,EAAK,EAAE,GAAA;AACT,CAAC","file":"index.js","sourcesContent":["/**\n * tv.ts — a tailwind-variants factory pre-configured for the M3 typescale.\n *\n * The Tailwind v4 preset exposes the 15 typescale roles as `text-<role>`\n * font-size utilities (e.g. `text-body-small`, `text-label-large`). Stock\n * tailwind-merge does not know these custom names, so it groups them with the\n * `text-<color>` utilities and drops one when a slot sets both a color *and* a\n * typescale (the common M3 case). That silently strips either the color or the\n * type, breaking token compliance.\n *\n * Teaching tailwind-merge that the typescale names belong to the `font-size`\n * group keeps color and type independent, so both survive the merge.\n */\nimport { type TV, tv as baseTv } from 'tailwind-variants';\n\nconst TYPESCALE = [\n 'display-large',\n 'display-medium',\n 'display-small',\n 'headline-large',\n 'headline-medium',\n 'headline-small',\n 'title-large',\n 'title-medium',\n 'title-small',\n 'body-large',\n 'body-medium',\n 'body-small',\n 'label-large',\n 'label-medium',\n 'label-small',\n] as const;\n\nexport const tv: TV = (options, config) =>\n baseTv(options, {\n ...config,\n twMergeConfig: {\n extend: {\n classGroups: {\n 'font-size': [{ text: [...TYPESCALE] }],\n },\n },\n },\n });\n","/**\n * bottom-app-bar.ts — tailwind-variants slots for the M3 BottomAppBar.\n *\n * An 80dp `surface-container` `role=\"toolbar\"`: leading action icons + an\n * optional trailing FAB. Same DOM as the VE build.\n */\nimport { createBottomAppBar } from '@m3-baseui/core';\nimport { tv } from '../../tv';\n\nexport const bottomAppBarTv = tv({\n slots: {\n root: 'flex items-center justify-between w-full box-border h-20 px-1 bg-surface-container text-on-surface-variant',\n actions: 'flex items-center gap-1 pl-2 [&_svg]:size-6',\n fab: 'flex items-center pr-3',\n },\n});\n\nconst s = bottomAppBarTv();\nexport const BottomAppBar = createBottomAppBar({\n root: s.root(),\n actions: s.actions(),\n fab: s.fab(),\n});\nexport type { BottomAppBarProps } from '@m3-baseui/core';\n"]}
1
+ {"version":3,"sources":["../../../src/tv.ts","../../../src/components/bottom-app-bar/bottom-app-bar.ts"],"names":["baseTv"],"mappings":";;;;;AAoBA,IAAM,SAAA,GAAY;AAAA,EAChB,eAAA;AAAA,EACA,gBAAA;AAAA,EACA,eAAA;AAAA,EACA,gBAAA;AAAA,EACA,iBAAA;AAAA,EACA,gBAAA;AAAA,EACA,aAAA;AAAA,EACA,cAAA;AAAA,EACA,aAAA;AAAA,EACA,YAAA;AAAA,EACA,aAAA;AAAA,EACA,YAAA;AAAA,EACA,aAAA;AAAA,EACA,cAAA;AAAA,EACA;AACF,CAAA;AAKA,IAAM,KAAA,GAAQ;AAAA,EACZ,MAAA;AAAA,EACA,aAAA;AAAA,EACA,OAAA;AAAA,EACA,QAAA;AAAA,EACA,OAAA;AAAA,EACA,iBAAA;AAAA,EACA,aAAA;AAAA,EACA,uBAAA;AAAA,EACA;AACF,CAAA;AAEO,IAAM,EAAA,GAAS,CAAC,OAAA,EAAS,MAAA,KAC9BA,KAAO,OAAA,EAAS;AAAA,EACd,GAAG,MAAA;AAAA,EACH,aAAA,EAAe;AAAA,IACb,MAAA,EAAQ;AAAA,MACN,WAAA,EAAa;AAAA,QACX,WAAA,EAAa,CAAC,EAAE,IAAA,EAAM,CAAC,GAAG,SAAS,GAAG,CAAA;AAAA,QACtC,OAAA,EAAS,CAAC,EAAE,OAAA,EAAS,CAAC,GAAG,KAAK,GAAG;AAAA;AACnC;AACF;AAEJ,CAAC,CAAA;;;ACvDI,IAAM,iBAAiB,EAAA,CAAG;AAAA,EAC/B,KAAA,EAAO;AAAA,IACL,IAAA,EAAM,4GAAA;AAAA,IACN,OAAA,EAAS,6CAAA;AAAA,IACT,GAAA,EAAK;AAAA;AAET,CAAC;AAED,IAAM,IAAI,cAAA,EAAe;AAClB,IAAM,eAAe,kBAAA,CAAmB;AAAA,EAC7C,IAAA,EAAM,EAAE,IAAA,EAAK;AAAA,EACb,OAAA,EAAS,EAAE,OAAA,EAAQ;AAAA,EACnB,GAAA,EAAK,EAAE,GAAA;AACT,CAAC","file":"index.js","sourcesContent":["/**\n * tv.ts — a tailwind-variants factory pre-configured for the M3 typescale and\n * shape scale.\n *\n * The Tailwind v4 preset exposes the 15 typescale roles as `text-<role>`\n * font-size utilities (e.g. `text-body-small`, `text-label-large`) and the\n * shape scale as `rounded-<role>` border-radius utilities (e.g. `rounded-small`,\n * `rounded-extra-large`). Stock tailwind-merge does not know these custom names,\n * so it (a) groups the typescale names with `text-<color>` and drops one when a\n * slot sets both a color *and* a typescale, and (b) fails to see two custom\n * `rounded-<role>` classes as conflicting, so a later corner override never\n * dedupes the resting one (both survive, and CSS source order — not intent —\n * decides). Either way token compliance / shape morph silently breaks.\n *\n * Teaching tailwind-merge that the typescale names belong to `font-size` and the\n * shape names belong to `rounded` keeps color and type independent and makes the\n * corner utilities override one another as expected.\n */\nimport { type TV, tv as baseTv } from 'tailwind-variants';\n\nconst TYPESCALE = [\n 'display-large',\n 'display-medium',\n 'display-small',\n 'headline-large',\n 'headline-medium',\n 'headline-small',\n 'title-large',\n 'title-medium',\n 'title-small',\n 'body-large',\n 'body-medium',\n 'body-small',\n 'label-large',\n 'label-medium',\n 'label-small',\n] as const;\n\n// M3 shape scale exposed as `rounded-<role>` (see @m3-baseui/tokens theme.css\n// `--radius-*`). `none` / `full` overlap stock Tailwind and are harmless to\n// re-list; the intermediate roles are what stock tailwind-merge misses.\nconst SHAPE = [\n 'none',\n 'extra-small',\n 'small',\n 'medium',\n 'large',\n 'large-increased',\n 'extra-large',\n 'extra-large-increased',\n 'full',\n] as const;\n\nexport const tv: TV = (options, config) =>\n baseTv(options, {\n ...config,\n twMergeConfig: {\n extend: {\n classGroups: {\n 'font-size': [{ text: [...TYPESCALE] }],\n rounded: [{ rounded: [...SHAPE] }],\n },\n },\n },\n });\n","/**\n * bottom-app-bar.ts — tailwind-variants slots for the M3 BottomAppBar.\n *\n * An 80dp `surface-container` `role=\"toolbar\"`: leading action icons + an\n * optional trailing FAB. Same DOM as the VE build.\n */\nimport { createBottomAppBar } from '@m3-baseui/core';\nimport { tv } from '../../tv';\n\nexport const bottomAppBarTv = tv({\n slots: {\n root: 'flex items-center justify-between w-full box-border h-20 px-1 bg-surface-container text-on-surface-variant',\n actions: 'flex items-center gap-1 pl-2 [&_svg]:size-6',\n fab: 'flex items-center pr-3',\n },\n});\n\nconst s = bottomAppBarTv();\nexport const BottomAppBar = createBottomAppBar({\n root: s.root(),\n actions: s.actions(),\n fab: s.fab(),\n});\nexport type { BottomAppBarProps } from '@m3-baseui/core';\n"]}
@@ -20,12 +20,24 @@ var TYPESCALE = [
20
20
  "label-medium",
21
21
  "label-small"
22
22
  ];
23
+ var SHAPE = [
24
+ "none",
25
+ "extra-small",
26
+ "small",
27
+ "medium",
28
+ "large",
29
+ "large-increased",
30
+ "extra-large",
31
+ "extra-large-increased",
32
+ "full"
33
+ ];
23
34
  var tv = (options, config) => tv$1(options, {
24
35
  ...config,
25
36
  twMergeConfig: {
26
37
  extend: {
27
38
  classGroups: {
28
- "font-size": [{ text: [...TYPESCALE] }]
39
+ "font-size": [{ text: [...TYPESCALE] }],
40
+ rounded: [{ rounded: [...SHAPE] }]
29
41
  }
30
42
  }
31
43
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/tv.ts","../../../src/components/bottom-sheet/bottom-sheet.ts"],"names":["baseTv"],"mappings":";;;;;AAeA,IAAM,SAAA,GAAY;AAAA,EAChB,eAAA;AAAA,EACA,gBAAA;AAAA,EACA,eAAA;AAAA,EACA,gBAAA;AAAA,EACA,iBAAA;AAAA,EACA,gBAAA;AAAA,EACA,aAAA;AAAA,EACA,cAAA;AAAA,EACA,aAAA;AAAA,EACA,YAAA;AAAA,EACA,aAAA;AAAA,EACA,YAAA;AAAA,EACA,aAAA;AAAA,EACA,cAAA;AAAA,EACA;AACF,CAAA;AAEO,IAAM,EAAA,GAAS,CAAC,OAAA,EAAS,MAAA,KAC9BA,KAAO,OAAA,EAAS;AAAA,EACd,GAAG,MAAA;AAAA,EACH,aAAA,EAAe;AAAA,IACb,MAAA,EAAQ;AAAA,MACN,WAAA,EAAa;AAAA,QACX,WAAA,EAAa,CAAC,EAAE,IAAA,EAAM,CAAC,GAAG,SAAS,GAAG;AAAA;AACxC;AACF;AAEJ,CAAC,CAAA;;;AC/BI,IAAM,gBAAgB,EAAA,CAAG;AAAA,EAC9B,KAAA,EAAO;AAAA,IACL,QAAA,EAAU;AAAA,MACR,gCAAA;AAAA,MACA,iDAAA;AAAA,MACA,gCAAA;AAAA,MACA;AAAA,KACF;AAAA,IACA,QAAA,EAAU,kDAAA;AAAA,IACV,KAAA,EAAO;AAAA,MACL,2DAAA;AAAA,MACA,4DAAA;AAAA,MACA,mFAAA;AAAA,MACA,8FAAA;AAAA,MACA,mDAAA;AAAA,MACA,4BAAA;AAAA,MACA;AAAA,KACF;AAAA,IACA,MAAA,EAAQ,0EAAA;AAAA,IACR,KAAA,EAAO,CAAC,gDAAgD,CAAA;AAAA,IACxD,WAAA,EAAa,CAAC,wDAAwD;AAAA;AAE1E,CAAC;AAED,IAAM,IAAI,aAAA,EAAc;AACjB,IAAM,cAAc,iBAAA,CAAkB;AAAA,EAC3C,QAAA,EAAU,EAAE,QAAA,EAAS;AAAA,EACrB,QAAA,EAAU,EAAE,QAAA,EAAS;AAAA,EACrB,KAAA,EAAO,EAAE,KAAA,EAAM;AAAA,EACf,MAAA,EAAQ,EAAE,MAAA,EAAO;AAAA,EACjB,KAAA,EAAO,EAAE,KAAA,EAAM;AAAA,EACf,WAAA,EAAa,EAAE,WAAA;AACjB,CAAC","file":"index.js","sourcesContent":["/**\n * tv.ts — a tailwind-variants factory pre-configured for the M3 typescale.\n *\n * The Tailwind v4 preset exposes the 15 typescale roles as `text-<role>`\n * font-size utilities (e.g. `text-body-small`, `text-label-large`). Stock\n * tailwind-merge does not know these custom names, so it groups them with the\n * `text-<color>` utilities and drops one when a slot sets both a color *and* a\n * typescale (the common M3 case). That silently strips either the color or the\n * type, breaking token compliance.\n *\n * Teaching tailwind-merge that the typescale names belong to the `font-size`\n * group keeps color and type independent, so both survive the merge.\n */\nimport { type TV, tv as baseTv } from 'tailwind-variants';\n\nconst TYPESCALE = [\n 'display-large',\n 'display-medium',\n 'display-small',\n 'headline-large',\n 'headline-medium',\n 'headline-small',\n 'title-large',\n 'title-medium',\n 'title-small',\n 'body-large',\n 'body-medium',\n 'body-small',\n 'label-large',\n 'label-medium',\n 'label-small',\n] as const;\n\nexport const tv: TV = (options, config) =>\n baseTv(options, {\n ...config,\n twMergeConfig: {\n extend: {\n classGroups: {\n 'font-size': [{ text: [...TYPESCALE] }],\n },\n },\n },\n });\n","/**\n * bottom-sheet.ts — tailwind-variants slots for the M3 Bottom sheet.\n *\n * A `surface-container-low` surface docked to the bottom edge with extra-large\n * (28dp) top corners, elevation 1, and a 32×4dp drag handle. The scrim fades on\n * Base UI's data-[starting-style] / data-[ending-style]; the popup slides via the\n * drawer's `--drawer-swipe-movement-y` so the swipe gesture tracks the finger.\n * Same DOM + `data-*` as the VE build.\n */\nimport { createBottomSheet } from '@m3-baseui/core';\nimport { tv } from '../../tv';\n\nexport const bottomSheetTv = tv({\n slots: {\n backdrop: [\n 'fixed inset-0 z-40 bg-scrim/32',\n 'transition-opacity duration-300 ease-emphasized',\n 'data-[swiping]:transition-none',\n 'data-[starting-style]:opacity-0 data-[ending-style]:opacity-0',\n ],\n viewport: 'fixed inset-0 z-50 flex items-end justify-center',\n popup: [\n 'box-border w-full max-w-[640px] max-h-[calc(100dvh-56px)]',\n 'overflow-y-auto overscroll-contain touch-auto outline-none',\n 'pb-6 bg-surface-container-low text-on-surface rounded-t-extra-large shadow-level1',\n '[transform:translateY(calc(var(--drawer-snap-point-offset)+var(--drawer-swipe-movement-y)))]',\n 'transition-transform duration-300 ease-emphasized',\n 'data-[swiping]:select-none',\n 'data-[starting-style]:[transform:translateY(100%)] data-[ending-style]:[transform:translateY(100%)]',\n ],\n handle: 'mx-auto mt-4 mb-2 h-1 w-8 shrink-0 rounded-full bg-on-surface-variant/40',\n title: ['m-0 px-6 pt-2 text-title-large text-on-surface'],\n description: ['m-0 px-6 pt-1 text-body-medium text-on-surface-variant'],\n },\n});\n\nconst s = bottomSheetTv();\nexport const BottomSheet = createBottomSheet({\n backdrop: s.backdrop(),\n viewport: s.viewport(),\n popup: s.popup(),\n handle: s.handle(),\n title: s.title(),\n description: s.description(),\n});\nexport type { BottomSheetVariant } from '@m3-baseui/core';\n"]}
1
+ {"version":3,"sources":["../../../src/tv.ts","../../../src/components/bottom-sheet/bottom-sheet.ts"],"names":["baseTv"],"mappings":";;;;;AAoBA,IAAM,SAAA,GAAY;AAAA,EAChB,eAAA;AAAA,EACA,gBAAA;AAAA,EACA,eAAA;AAAA,EACA,gBAAA;AAAA,EACA,iBAAA;AAAA,EACA,gBAAA;AAAA,EACA,aAAA;AAAA,EACA,cAAA;AAAA,EACA,aAAA;AAAA,EACA,YAAA;AAAA,EACA,aAAA;AAAA,EACA,YAAA;AAAA,EACA,aAAA;AAAA,EACA,cAAA;AAAA,EACA;AACF,CAAA;AAKA,IAAM,KAAA,GAAQ;AAAA,EACZ,MAAA;AAAA,EACA,aAAA;AAAA,EACA,OAAA;AAAA,EACA,QAAA;AAAA,EACA,OAAA;AAAA,EACA,iBAAA;AAAA,EACA,aAAA;AAAA,EACA,uBAAA;AAAA,EACA;AACF,CAAA;AAEO,IAAM,EAAA,GAAS,CAAC,OAAA,EAAS,MAAA,KAC9BA,KAAO,OAAA,EAAS;AAAA,EACd,GAAG,MAAA;AAAA,EACH,aAAA,EAAe;AAAA,IACb,MAAA,EAAQ;AAAA,MACN,WAAA,EAAa;AAAA,QACX,WAAA,EAAa,CAAC,EAAE,IAAA,EAAM,CAAC,GAAG,SAAS,GAAG,CAAA;AAAA,QACtC,OAAA,EAAS,CAAC,EAAE,OAAA,EAAS,CAAC,GAAG,KAAK,GAAG;AAAA;AACnC;AACF;AAEJ,CAAC,CAAA;;;ACpDI,IAAM,gBAAgB,EAAA,CAAG;AAAA,EAC9B,KAAA,EAAO;AAAA,IACL,QAAA,EAAU;AAAA,MACR,gCAAA;AAAA,MACA,iDAAA;AAAA,MACA,gCAAA;AAAA,MACA;AAAA,KACF;AAAA,IACA,QAAA,EAAU,kDAAA;AAAA,IACV,KAAA,EAAO;AAAA,MACL,2DAAA;AAAA,MACA,4DAAA;AAAA,MACA,mFAAA;AAAA,MACA,8FAAA;AAAA,MACA,mDAAA;AAAA,MACA,4BAAA;AAAA,MACA;AAAA,KACF;AAAA,IACA,MAAA,EAAQ,0EAAA;AAAA,IACR,KAAA,EAAO,CAAC,gDAAgD,CAAA;AAAA,IACxD,WAAA,EAAa,CAAC,wDAAwD;AAAA;AAE1E,CAAC;AAED,IAAM,IAAI,aAAA,EAAc;AACjB,IAAM,cAAc,iBAAA,CAAkB;AAAA,EAC3C,QAAA,EAAU,EAAE,QAAA,EAAS;AAAA,EACrB,QAAA,EAAU,EAAE,QAAA,EAAS;AAAA,EACrB,KAAA,EAAO,EAAE,KAAA,EAAM;AAAA,EACf,MAAA,EAAQ,EAAE,MAAA,EAAO;AAAA,EACjB,KAAA,EAAO,EAAE,KAAA,EAAM;AAAA,EACf,WAAA,EAAa,EAAE,WAAA;AACjB,CAAC","file":"index.js","sourcesContent":["/**\n * tv.ts — a tailwind-variants factory pre-configured for the M3 typescale and\n * shape scale.\n *\n * The Tailwind v4 preset exposes the 15 typescale roles as `text-<role>`\n * font-size utilities (e.g. `text-body-small`, `text-label-large`) and the\n * shape scale as `rounded-<role>` border-radius utilities (e.g. `rounded-small`,\n * `rounded-extra-large`). Stock tailwind-merge does not know these custom names,\n * so it (a) groups the typescale names with `text-<color>` and drops one when a\n * slot sets both a color *and* a typescale, and (b) fails to see two custom\n * `rounded-<role>` classes as conflicting, so a later corner override never\n * dedupes the resting one (both survive, and CSS source order — not intent —\n * decides). Either way token compliance / shape morph silently breaks.\n *\n * Teaching tailwind-merge that the typescale names belong to `font-size` and the\n * shape names belong to `rounded` keeps color and type independent and makes the\n * corner utilities override one another as expected.\n */\nimport { type TV, tv as baseTv } from 'tailwind-variants';\n\nconst TYPESCALE = [\n 'display-large',\n 'display-medium',\n 'display-small',\n 'headline-large',\n 'headline-medium',\n 'headline-small',\n 'title-large',\n 'title-medium',\n 'title-small',\n 'body-large',\n 'body-medium',\n 'body-small',\n 'label-large',\n 'label-medium',\n 'label-small',\n] as const;\n\n// M3 shape scale exposed as `rounded-<role>` (see @m3-baseui/tokens theme.css\n// `--radius-*`). `none` / `full` overlap stock Tailwind and are harmless to\n// re-list; the intermediate roles are what stock tailwind-merge misses.\nconst SHAPE = [\n 'none',\n 'extra-small',\n 'small',\n 'medium',\n 'large',\n 'large-increased',\n 'extra-large',\n 'extra-large-increased',\n 'full',\n] as const;\n\nexport const tv: TV = (options, config) =>\n baseTv(options, {\n ...config,\n twMergeConfig: {\n extend: {\n classGroups: {\n 'font-size': [{ text: [...TYPESCALE] }],\n rounded: [{ rounded: [...SHAPE] }],\n },\n },\n },\n });\n","/**\n * bottom-sheet.ts — tailwind-variants slots for the M3 Bottom sheet.\n *\n * A `surface-container-low` surface docked to the bottom edge with extra-large\n * (28dp) top corners, elevation 1, and a 32×4dp drag handle. The scrim fades on\n * Base UI's data-[starting-style] / data-[ending-style]; the popup slides via the\n * drawer's `--drawer-swipe-movement-y` so the swipe gesture tracks the finger.\n * Same DOM + `data-*` as the VE build.\n */\nimport { createBottomSheet } from '@m3-baseui/core';\nimport { tv } from '../../tv';\n\nexport const bottomSheetTv = tv({\n slots: {\n backdrop: [\n 'fixed inset-0 z-40 bg-scrim/32',\n 'transition-opacity duration-300 ease-emphasized',\n 'data-[swiping]:transition-none',\n 'data-[starting-style]:opacity-0 data-[ending-style]:opacity-0',\n ],\n viewport: 'fixed inset-0 z-50 flex items-end justify-center',\n popup: [\n 'box-border w-full max-w-[640px] max-h-[calc(100dvh-56px)]',\n 'overflow-y-auto overscroll-contain touch-auto outline-none',\n 'pb-6 bg-surface-container-low text-on-surface rounded-t-extra-large shadow-level1',\n '[transform:translateY(calc(var(--drawer-snap-point-offset)+var(--drawer-swipe-movement-y)))]',\n 'transition-transform duration-300 ease-emphasized',\n 'data-[swiping]:select-none',\n 'data-[starting-style]:[transform:translateY(100%)] data-[ending-style]:[transform:translateY(100%)]',\n ],\n handle: 'mx-auto mt-4 mb-2 h-1 w-8 shrink-0 rounded-full bg-on-surface-variant/40',\n title: ['m-0 px-6 pt-2 text-title-large text-on-surface'],\n description: ['m-0 px-6 pt-1 text-body-medium text-on-surface-variant'],\n },\n});\n\nconst s = bottomSheetTv();\nexport const BottomSheet = createBottomSheet({\n backdrop: s.backdrop(),\n viewport: s.viewport(),\n popup: s.popup(),\n handle: s.handle(),\n title: s.title(),\n description: s.description(),\n});\nexport type { BottomSheetVariant } from '@m3-baseui/core';\n"]}
@@ -1,7 +1,7 @@
1
1
  import * as _base_ui_react from '@base-ui/react';
2
2
  import * as react from 'react';
3
3
  import * as _m3_baseui_core from '@m3-baseui/core';
4
- export { ButtonProps, ButtonVariant } from '@m3-baseui/core';
4
+ export { ButtonProps, ButtonShape, ButtonSize, ButtonVariant } from '@m3-baseui/core';
5
5
  import * as tailwind_variants from 'tailwind-variants';
6
6
  import * as tailwind_variants_dist_config_js from 'tailwind-variants/dist/config.js';
7
7
 
@@ -13,6 +13,21 @@ declare const button: tailwind_variants.TVReturnType<{
13
13
  elevated: string[];
14
14
  text: string[];
15
15
  };
16
+ size: {
17
+ xs: string[];
18
+ s: string[];
19
+ m: string[];
20
+ l: string[];
21
+ xl: string[];
22
+ };
23
+ shape: {
24
+ round: string;
25
+ square: string;
26
+ };
27
+ toggle: {
28
+ on: string;
29
+ off: string;
30
+ };
16
31
  }, undefined, string[], tailwind_variants_dist_config_js.TVConfig<{
17
32
  variant: {
18
33
  filled: string[];
@@ -21,6 +36,21 @@ declare const button: tailwind_variants.TVReturnType<{
21
36
  elevated: string[];
22
37
  text: string[];
23
38
  };
39
+ size: {
40
+ xs: string[];
41
+ s: string[];
42
+ m: string[];
43
+ l: string[];
44
+ xl: string[];
45
+ };
46
+ shape: {
47
+ round: string;
48
+ square: string;
49
+ };
50
+ toggle: {
51
+ on: string;
52
+ off: string;
53
+ };
24
54
  }, {
25
55
  variant: {
26
56
  filled: string[];
@@ -29,6 +59,21 @@ declare const button: tailwind_variants.TVReturnType<{
29
59
  elevated: string[];
30
60
  text: string[];
31
61
  };
62
+ size: {
63
+ xs: string[];
64
+ s: string[];
65
+ m: string[];
66
+ l: string[];
67
+ xl: string[];
68
+ };
69
+ shape: {
70
+ round: string;
71
+ square: string;
72
+ };
73
+ toggle: {
74
+ on: string;
75
+ off: string;
76
+ };
32
77
  }>, {
33
78
  variant: {
34
79
  filled: string[];
@@ -37,6 +82,21 @@ declare const button: tailwind_variants.TVReturnType<{
37
82
  elevated: string[];
38
83
  text: string[];
39
84
  };
85
+ size: {
86
+ xs: string[];
87
+ s: string[];
88
+ m: string[];
89
+ l: string[];
90
+ xl: string[];
91
+ };
92
+ shape: {
93
+ round: string;
94
+ square: string;
95
+ };
96
+ toggle: {
97
+ on: string;
98
+ off: string;
99
+ };
40
100
  }, undefined, tailwind_variants.TVReturnType<{
41
101
  variant: {
42
102
  filled: string[];
@@ -45,6 +105,21 @@ declare const button: tailwind_variants.TVReturnType<{
45
105
  elevated: string[];
46
106
  text: string[];
47
107
  };
108
+ size: {
109
+ xs: string[];
110
+ s: string[];
111
+ m: string[];
112
+ l: string[];
113
+ xl: string[];
114
+ };
115
+ shape: {
116
+ round: string;
117
+ square: string;
118
+ };
119
+ toggle: {
120
+ on: string;
121
+ off: string;
122
+ };
48
123
  }, undefined, string[], tailwind_variants_dist_config_js.TVConfig<{
49
124
  variant: {
50
125
  filled: string[];
@@ -53,6 +128,21 @@ declare const button: tailwind_variants.TVReturnType<{
53
128
  elevated: string[];
54
129
  text: string[];
55
130
  };
131
+ size: {
132
+ xs: string[];
133
+ s: string[];
134
+ m: string[];
135
+ l: string[];
136
+ xl: string[];
137
+ };
138
+ shape: {
139
+ round: string;
140
+ square: string;
141
+ };
142
+ toggle: {
143
+ on: string;
144
+ off: string;
145
+ };
56
146
  }, {
57
147
  variant: {
58
148
  filled: string[];
@@ -61,6 +151,21 @@ declare const button: tailwind_variants.TVReturnType<{
61
151
  elevated: string[];
62
152
  text: string[];
63
153
  };
154
+ size: {
155
+ xs: string[];
156
+ s: string[];
157
+ m: string[];
158
+ l: string[];
159
+ xl: string[];
160
+ };
161
+ shape: {
162
+ round: string;
163
+ square: string;
164
+ };
165
+ toggle: {
166
+ on: string;
167
+ off: string;
168
+ };
64
169
  }>, unknown, unknown, undefined>>;
65
170
  declare const Button: react.ForwardRefExoticComponent<_m3_baseui_core.ButtonOwnProps & Omit<react.ButtonHTMLAttributes<HTMLButtonElement>, "color"> & {
66
171
  render?: _base_ui_react.useRender.RenderProp;
@@ -1,19 +1,58 @@
1
1
  "use client";
2
- import { createButton } from '@m3-baseui/core';
3
- import { tv } from 'tailwind-variants';
2
+ import { createButton, toToggle } from '@m3-baseui/core';
3
+ import { tv as tv$1 } from 'tailwind-variants';
4
+
5
+ // src/components/button/button.ts
6
+ var TYPESCALE = [
7
+ "display-large",
8
+ "display-medium",
9
+ "display-small",
10
+ "headline-large",
11
+ "headline-medium",
12
+ "headline-small",
13
+ "title-large",
14
+ "title-medium",
15
+ "title-small",
16
+ "body-large",
17
+ "body-medium",
18
+ "body-small",
19
+ "label-large",
20
+ "label-medium",
21
+ "label-small"
22
+ ];
23
+ var SHAPE = [
24
+ "none",
25
+ "extra-small",
26
+ "small",
27
+ "medium",
28
+ "large",
29
+ "large-increased",
30
+ "extra-large",
31
+ "extra-large-increased",
32
+ "full"
33
+ ];
34
+ var tv = (options, config) => tv$1(options, {
35
+ ...config,
36
+ twMergeConfig: {
37
+ extend: {
38
+ classGroups: {
39
+ "font-size": [{ text: [...TYPESCALE] }],
40
+ rounded: [{ rounded: [...SHAPE] }]
41
+ }
42
+ }
43
+ }
44
+ });
4
45
 
5
46
  // src/components/button/button.ts
6
47
  var button = tv({
7
48
  base: [
8
- "relative inline-flex items-center justify-center gap-2",
9
- "h-10 px-6 rounded-full overflow-hidden cursor-pointer select-none border-0",
10
- "text-label-large",
11
- // M3 with-icon padding: the icon side trims to 16dp (label side stays 24dp).
12
- "data-[with-start-icon]:pl-4 data-[with-end-icon]:pr-4",
13
- // Icon slot: 18dp, centered.
49
+ "relative inline-flex items-center justify-center",
50
+ "overflow-hidden cursor-pointer select-none border-0",
51
+ // Icon slot: centered; the svg size comes from the `size` variant.
14
52
  "[&_[data-slot=button-icon]]:inline-flex [&_[data-slot=button-icon]]:items-center [&_[data-slot=button-icon]]:justify-center",
15
- "[&_[data-slot=button-icon]>svg]:size-[18px]",
16
- "transition-[box-shadow,background-color,color,border-color] duration-200 ease-[var(--md-sys-motion-easing-standard)]",
53
+ // Motion: Compose uses DefaultEffects (critically-damped spring, no bounce)
54
+ // for the shape/color/elevation transitions — spring-effects-default here.
55
+ "transition-[box-shadow,background-color,color,border-color,border-radius] duration-200 ease-spring-effects-default",
17
56
  // State layer overlay
18
57
  "before:absolute before:inset-0 before:rounded-[inherit] before:bg-current before:opacity-0 before:pointer-events-none",
19
58
  "before:transition-opacity before:duration-100",
@@ -24,20 +63,23 @@ var button = tv({
24
63
  // Focus ring (M3: 3px secondary, 2px offset)
25
64
  "focus-visible:outline-[3px] focus-visible:outline-offset-2 focus-visible:outline-secondary",
26
65
  // Disabled: no interaction, no state layer, no elevation. Per-variant
27
- // colors (container on-surface/12, label on-surface/38) live on each variant.
66
+ // colors (container on-surface/10, label on-surface-variant/38) live on
67
+ // each variant.
28
68
  "disabled:pointer-events-none disabled:shadow-none disabled:before:opacity-0",
29
69
  "data-[disabled]:pointer-events-none data-[disabled]:shadow-none data-[disabled]:before:opacity-0"
30
70
  ],
31
71
  variants: {
32
72
  // M3 elevation per variant: filled/tonal rest level0→hover level1→pressed level0;
33
- // elevated rest level1→hover level2→pressed level1. Disabled container is
34
- // on-surface/12 and label on-surface/38, matching material-web.
73
+ // elevated rest level1→hover level2→pressed level1. Expressive disabled:
74
+ // container on-surface/10, label on-surface-variant/38 — except tonal, which
75
+ // is unchanged upstream (FilledTonalButtonTokens v0_103) and keeps 0.12 /
76
+ // on-surface. Expressive also moves outlined/text labels to on-surface-variant.
35
77
  variant: {
36
78
  filled: [
37
79
  "bg-primary text-on-primary",
38
80
  "hover:shadow-level1 focus-visible:shadow-none active:shadow-none data-[pressed]:shadow-none",
39
- "disabled:bg-on-surface/12 disabled:text-on-surface/38",
40
- "data-[disabled]:bg-on-surface/12 data-[disabled]:text-on-surface/38"
81
+ "disabled:bg-on-surface/10 disabled:text-on-surface-variant/38",
82
+ "data-[disabled]:bg-on-surface/10 data-[disabled]:text-on-surface-variant/38"
41
83
  ],
42
84
  tonal: [
43
85
  "bg-secondary-container text-on-secondary-container",
@@ -46,28 +88,129 @@ var button = tv({
46
88
  "data-[disabled]:bg-on-surface/12 data-[disabled]:text-on-surface/38"
47
89
  ],
48
90
  outlined: [
49
- "bg-transparent text-primary border border-outline",
50
- "disabled:text-on-surface/38 disabled:border-on-surface/12",
51
- "data-[disabled]:text-on-surface/38 data-[disabled]:border-on-surface/12"
91
+ "bg-transparent text-on-surface-variant border border-outline-variant",
92
+ // Compose outlinedButtonBorder(enabled=false) tints the outline with
93
+ // DisabledContainerOpacity (0.1), so the disabled border is faint.
94
+ "disabled:text-on-surface-variant/38 disabled:border-outline-variant/10",
95
+ "data-[disabled]:text-on-surface-variant/38 data-[disabled]:border-outline-variant/10"
52
96
  ],
53
97
  elevated: [
54
98
  "bg-surface-container-low text-primary shadow-level1",
55
99
  "hover:shadow-level2 focus-visible:shadow-level1 active:shadow-level1 data-[pressed]:shadow-level1",
56
- "disabled:bg-on-surface/12 disabled:text-on-surface/38",
57
- "data-[disabled]:bg-on-surface/12 data-[disabled]:text-on-surface/38"
100
+ "disabled:bg-on-surface/10 disabled:text-on-surface-variant/38",
101
+ "data-[disabled]:bg-on-surface/10 data-[disabled]:text-on-surface-variant/38"
58
102
  ],
59
103
  text: [
60
- "bg-transparent text-primary px-3",
61
- "disabled:text-on-surface/38",
62
- "data-[disabled]:text-on-surface/38"
104
+ "bg-transparent text-on-surface-variant",
105
+ "disabled:text-on-surface-variant/38",
106
+ "data-[disabled]:text-on-surface-variant/38"
107
+ ]
108
+ },
109
+ // Height / horizontal padding / gap / typescale / icon size per Expressive
110
+ // size. The pressed corner morph (PressedContainerShape: XS·S small 8 /
111
+ // M medium 12 / L·XL large 16) rides on data-[pressed]/active here so its
112
+ // attribute-selector specificity wins over the resting `rounded-*`.
113
+ size: {
114
+ xs: [
115
+ // XS is special-cased in Compose Button.kt: contentPaddingFor returns
116
+ // ExtraSmallContentPadding (12dp) and iconSpacingFor returns
117
+ // ExtraSmallIconSpacing (4dp) — tighter than the ButtonXSmallTokens
118
+ // Leading/TrailingSpace (16) and IconLabelSpace (8). S–XL use their tokens.
119
+ "h-8 px-3 gap-1 text-label-large [&_[data-slot=button-icon]>svg]:size-5",
120
+ "data-[pressed]:rounded-small active:rounded-small"
121
+ ],
122
+ s: [
123
+ "h-10 px-4 gap-2 text-label-large [&_[data-slot=button-icon]>svg]:size-5",
124
+ "data-[pressed]:rounded-small active:rounded-small"
125
+ ],
126
+ m: [
127
+ "h-14 px-6 gap-2 text-title-medium [&_[data-slot=button-icon]>svg]:size-6",
128
+ "data-[pressed]:rounded-medium active:rounded-medium"
129
+ ],
130
+ l: [
131
+ "h-24 px-12 gap-3 text-headline-small [&_[data-slot=button-icon]>svg]:size-8",
132
+ "data-[pressed]:rounded-large active:rounded-large"
133
+ ],
134
+ xl: [
135
+ "h-[136px] px-16 gap-4 text-headline-large [&_[data-slot=button-icon]>svg]:size-10",
136
+ "data-[pressed]:rounded-large active:rounded-large"
63
137
  ]
138
+ },
139
+ // round = full pill; the square corner is size-specific (compounds below).
140
+ shape: {
141
+ round: "rounded-full",
142
+ square: ""
143
+ },
144
+ // Toggle state, string-keyed so a plain (non-toggle) button — `toggle`
145
+ // unset — fires neither compound below (a boolean variant would default to
146
+ // `off` in tailwind-variants and wrongly apply the unselected look).
147
+ toggle: {
148
+ on: "",
149
+ off: ""
64
150
  }
65
151
  },
152
+ compoundVariants: [
153
+ // ---- Resting square corner (ContainerShapeSquare) ---------------------
154
+ { shape: "square", size: "xs", class: "rounded-medium" },
155
+ // 12dp
156
+ { shape: "square", size: "s", class: "rounded-medium" },
157
+ // 12dp
158
+ { shape: "square", size: "m", class: "rounded-large" },
159
+ // 16dp
160
+ { shape: "square", size: "l", class: "rounded-extra-large" },
161
+ // 28dp
162
+ { shape: "square", size: "xl", class: "rounded-extra-large" },
163
+ // 28dp
164
+ // ---- Selected shape morph: swap to the opposite shape -----------------
165
+ // (listed after the resting corner so tailwind-merge keeps these).
166
+ { shape: "round", toggle: "on", size: "xs", class: "rounded-medium" },
167
+ { shape: "round", toggle: "on", size: "s", class: "rounded-medium" },
168
+ { shape: "round", toggle: "on", size: "m", class: "rounded-large" },
169
+ { shape: "round", toggle: "on", size: "l", class: "rounded-extra-large" },
170
+ { shape: "round", toggle: "on", size: "xl", class: "rounded-extra-large" },
171
+ { shape: "square", toggle: "on", size: "xs", class: "rounded-full" },
172
+ { shape: "square", toggle: "on", size: "s", class: "rounded-full" },
173
+ { shape: "square", toggle: "on", size: "m", class: "rounded-full" },
174
+ { shape: "square", toggle: "on", size: "l", class: "rounded-full" },
175
+ { shape: "square", toggle: "on", size: "xl", class: "rounded-full" },
176
+ // ---- Outlined border width (OutlinedOutlineWidth: L 2 / XL 3 dp) ------
177
+ { variant: "outlined", size: "l", class: "border-2" },
178
+ { variant: "outlined", size: "xl", class: "border-[3px]" },
179
+ // ---- Toggle colors (Selected*/Unselected* tokens) ---------------------
180
+ // filled/tonal: base = default & selected look; `toggle:off` = unselected.
181
+ { variant: "filled", toggle: "off", class: "bg-surface-container text-on-surface-variant" },
182
+ { variant: "tonal", toggle: "off", class: "bg-surface-container text-on-surface-variant" },
183
+ // elevated: distinct selected (primary) & unselected looks.
184
+ { variant: "elevated", toggle: "on", class: "bg-primary text-on-primary" },
185
+ {
186
+ variant: "elevated",
187
+ toggle: "off",
188
+ class: "bg-surface-container-low text-on-surface-variant"
189
+ },
190
+ // outlined: selected fills with the inverse surface (base = unselected).
191
+ {
192
+ variant: "outlined",
193
+ toggle: "on",
194
+ class: [
195
+ "bg-inverse-surface text-inverse-on-surface border-transparent",
196
+ "disabled:bg-on-surface/10 disabled:border-transparent",
197
+ "data-[disabled]:bg-on-surface/10 data-[disabled]:border-transparent"
198
+ ]
199
+ },
200
+ // text: no Selected/Unselected tokens exist upstream (TextButtonTokens),
201
+ // so selection raises the label emphasis to primary (base = unselected
202
+ // on-surface-variant) to communicate the toggle state.
203
+ { variant: "text", toggle: "on", class: "text-primary" }
204
+ ],
66
205
  defaultVariants: {
67
- variant: "filled"
206
+ variant: "filled",
207
+ size: "s",
208
+ shape: "round"
68
209
  }
69
210
  });
70
- var Button = createButton(({ variant }) => button({ variant }));
211
+ var Button = createButton(
212
+ ({ variant, size, shape, selected }) => button({ variant, size, shape, toggle: toToggle(selected) })
213
+ );
71
214
 
72
215
  export { Button, button };
73
216
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/button/button.ts"],"names":[],"mappings":";;;;;AAcO,IAAM,SAAS,EAAA,CAAG;AAAA,EACvB,IAAA,EAAM;AAAA,IACJ,wDAAA;AAAA,IACA,4EAAA;AAAA,IACA,kBAAA;AAAA;AAAA,IAEA,uDAAA;AAAA;AAAA,IAEA,6HAAA;AAAA,IACA,6CAAA;AAAA,IACA,sHAAA;AAAA;AAAA,IAEA,uHAAA;AAAA,IACA,+CAAA;AAAA,IACA,kDAAA;AAAA,IACA,0DAAA;AAAA,IACA,qDAAA;AAAA,IACA,6DAAA;AAAA;AAAA,IAEA,4FAAA;AAAA;AAAA;AAAA,IAGA,6EAAA;AAAA,IACA;AAAA,GACF;AAAA,EACA,QAAA,EAAU;AAAA;AAAA;AAAA;AAAA,IAIR,OAAA,EAAS;AAAA,MACP,MAAA,EAAQ;AAAA,QACN,4BAAA;AAAA,QACA,6FAAA;AAAA,QACA,uDAAA;AAAA,QACA;AAAA,OACF;AAAA,MACA,KAAA,EAAO;AAAA,QACL,oDAAA;AAAA,QACA,6FAAA;AAAA,QACA,uDAAA;AAAA,QACA;AAAA,OACF;AAAA,MACA,QAAA,EAAU;AAAA,QACR,mDAAA;AAAA,QACA,2DAAA;AAAA,QACA;AAAA,OACF;AAAA,MACA,QAAA,EAAU;AAAA,QACR,qDAAA;AAAA,QACA,mGAAA;AAAA,QACA,uDAAA;AAAA,QACA;AAAA,OACF;AAAA,MACA,IAAA,EAAM;AAAA,QACJ,kCAAA;AAAA,QACA,6BAAA;AAAA,QACA;AAAA;AACF;AACF,GACF;AAAA,EACA,eAAA,EAAiB;AAAA,IACf,OAAA,EAAS;AAAA;AAEb,CAAC;AAEM,IAAM,MAAA,GAAS,YAAA,CAAa,CAAC,EAAE,OAAA,OAAc,MAAA,CAAO,EAAE,OAAA,EAAS,CAAC","file":"index.js","sourcesContent":["/**\n * button.ts — tailwind-variants resolver wired into the shared factory.\n *\n * Emits the same DOM and `data-*` state as the vanilla-extract build; only the\n * class strings differ. Utilities such as `bg-primary`, `text-on-primary`,\n * `rounded-full`, `shadow-level1`, and `text-label-large` are produced by the\n * Tailwind v4 `@theme` preset shipped in `@m3-baseui/tokens/theme.css`.\n *\n * Opacity modifiers (`before:opacity-[var(--md-sys-state-hover)]`) drive the\n * state layer off the channel-triple colors.\n */\nimport { createButton } from '@m3-baseui/core';\nimport { tv } from 'tailwind-variants';\n\nexport const button = tv({\n base: [\n 'relative inline-flex items-center justify-center gap-2',\n 'h-10 px-6 rounded-full overflow-hidden cursor-pointer select-none border-0',\n 'text-label-large',\n // M3 with-icon padding: the icon side trims to 16dp (label side stays 24dp).\n 'data-[with-start-icon]:pl-4 data-[with-end-icon]:pr-4',\n // Icon slot: 18dp, centered.\n '[&_[data-slot=button-icon]]:inline-flex [&_[data-slot=button-icon]]:items-center [&_[data-slot=button-icon]]:justify-center',\n '[&_[data-slot=button-icon]>svg]:size-[18px]',\n 'transition-[box-shadow,background-color,color,border-color] duration-200 ease-[var(--md-sys-motion-easing-standard)]',\n // State layer overlay\n 'before:absolute before:inset-0 before:rounded-[inherit] before:bg-current before:opacity-0 before:pointer-events-none',\n 'before:transition-opacity before:duration-100',\n 'hover:before:opacity-[var(--md-sys-state-hover)]',\n 'focus-visible:before:opacity-[var(--md-sys-state-focus)]',\n 'active:before:opacity-[var(--md-sys-state-pressed)]',\n 'data-[pressed]:before:opacity-[var(--md-sys-state-pressed)]',\n // Focus ring (M3: 3px secondary, 2px offset)\n 'focus-visible:outline-[3px] focus-visible:outline-offset-2 focus-visible:outline-secondary',\n // Disabled: no interaction, no state layer, no elevation. Per-variant\n // colors (container on-surface/12, label on-surface/38) live on each variant.\n 'disabled:pointer-events-none disabled:shadow-none disabled:before:opacity-0',\n 'data-[disabled]:pointer-events-none data-[disabled]:shadow-none data-[disabled]:before:opacity-0',\n ],\n variants: {\n // M3 elevation per variant: filled/tonal rest level0→hover level1→pressed level0;\n // elevated rest level1→hover level2→pressed level1. Disabled container is\n // on-surface/12 and label on-surface/38, matching material-web.\n variant: {\n filled: [\n 'bg-primary text-on-primary',\n 'hover:shadow-level1 focus-visible:shadow-none active:shadow-none data-[pressed]:shadow-none',\n 'disabled:bg-on-surface/12 disabled:text-on-surface/38',\n 'data-[disabled]:bg-on-surface/12 data-[disabled]:text-on-surface/38',\n ],\n tonal: [\n 'bg-secondary-container text-on-secondary-container',\n 'hover:shadow-level1 focus-visible:shadow-none active:shadow-none data-[pressed]:shadow-none',\n 'disabled:bg-on-surface/12 disabled:text-on-surface/38',\n 'data-[disabled]:bg-on-surface/12 data-[disabled]:text-on-surface/38',\n ],\n outlined: [\n 'bg-transparent text-primary border border-outline',\n 'disabled:text-on-surface/38 disabled:border-on-surface/12',\n 'data-[disabled]:text-on-surface/38 data-[disabled]:border-on-surface/12',\n ],\n elevated: [\n 'bg-surface-container-low text-primary shadow-level1',\n 'hover:shadow-level2 focus-visible:shadow-level1 active:shadow-level1 data-[pressed]:shadow-level1',\n 'disabled:bg-on-surface/12 disabled:text-on-surface/38',\n 'data-[disabled]:bg-on-surface/12 data-[disabled]:text-on-surface/38',\n ],\n text: [\n 'bg-transparent text-primary px-3',\n 'disabled:text-on-surface/38',\n 'data-[disabled]:text-on-surface/38',\n ],\n },\n },\n defaultVariants: {\n variant: 'filled',\n },\n});\n\nexport const Button = createButton(({ variant }) => button({ variant }));\nexport type { ButtonProps, ButtonVariant } from '@m3-baseui/core';\n"]}
1
+ {"version":3,"sources":["../../../src/tv.ts","../../../src/components/button/button.ts"],"names":["baseTv"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * tv.ts — a tailwind-variants factory pre-configured for the M3 typescale and\n * shape scale.\n *\n * The Tailwind v4 preset exposes the 15 typescale roles as `text-<role>`\n * font-size utilities (e.g. `text-body-small`, `text-label-large`) and the\n * shape scale as `rounded-<role>` border-radius utilities (e.g. `rounded-small`,\n * `rounded-extra-large`). Stock tailwind-merge does not know these custom names,\n * so it (a) groups the typescale names with `text-<color>` and drops one when a\n * slot sets both a color *and* a typescale, and (b) fails to see two custom\n * `rounded-<role>` classes as conflicting, so a later corner override never\n * dedupes the resting one (both survive, and CSS source order — not intent —\n * decides). Either way token compliance / shape morph silently breaks.\n *\n * Teaching tailwind-merge that the typescale names belong to `font-size` and the\n * shape names belong to `rounded` keeps color and type independent and makes the\n * corner utilities override one another as expected.\n */\nimport { type TV, tv as baseTv } from 'tailwind-variants';\n\nconst TYPESCALE = [\n 'display-large',\n 'display-medium',\n 'display-small',\n 'headline-large',\n 'headline-medium',\n 'headline-small',\n 'title-large',\n 'title-medium',\n 'title-small',\n 'body-large',\n 'body-medium',\n 'body-small',\n 'label-large',\n 'label-medium',\n 'label-small',\n] as const;\n\n// M3 shape scale exposed as `rounded-<role>` (see @m3-baseui/tokens theme.css\n// `--radius-*`). `none` / `full` overlap stock Tailwind and are harmless to\n// re-list; the intermediate roles are what stock tailwind-merge misses.\nconst SHAPE = [\n 'none',\n 'extra-small',\n 'small',\n 'medium',\n 'large',\n 'large-increased',\n 'extra-large',\n 'extra-large-increased',\n 'full',\n] as const;\n\nexport const tv: TV = (options, config) =>\n baseTv(options, {\n ...config,\n twMergeConfig: {\n extend: {\n classGroups: {\n 'font-size': [{ text: [...TYPESCALE] }],\n rounded: [{ rounded: [...SHAPE] }],\n },\n },\n },\n });\n","/**\n * button.ts — tailwind-variants resolver wired into the shared factory.\n *\n * Emits the same DOM and `data-*` state as the vanilla-extract build; only the\n * class strings differ. Utilities such as `bg-primary`, `text-on-primary`,\n * `rounded-full`, `shadow-level1`, and `text-label-large` are produced by the\n * Tailwind v4 `@theme` preset shipped in `@m3-baseui/tokens/theme.css`.\n *\n * M3 Expressive: five sizes (XS 32 → XL 136 dp) drive height / horizontal\n * padding / gap / typescale / icon size; `shape` picks the resting corner\n * (round=full pill vs a size-specific square), the corner morphs smaller on\n * press, and toggle buttons (`selected`) swap to the opposite shape plus the\n * Selected/Unselected color set. Opacity modifiers\n * (`before:opacity-[var(--md-sys-state-hover)]`) drive the state layer off the\n * channel-triple colors.\n */\nimport { createButton, toToggle } from '@m3-baseui/core';\nimport { tv } from '../../tv';\n\nexport const button = tv({\n base: [\n 'relative inline-flex items-center justify-center',\n 'overflow-hidden cursor-pointer select-none border-0',\n // Icon slot: centered; the svg size comes from the `size` variant.\n '[&_[data-slot=button-icon]]:inline-flex [&_[data-slot=button-icon]]:items-center [&_[data-slot=button-icon]]:justify-center',\n // Motion: Compose uses DefaultEffects (critically-damped spring, no bounce)\n // for the shape/color/elevation transitions — spring-effects-default here.\n 'transition-[box-shadow,background-color,color,border-color,border-radius] duration-200 ease-spring-effects-default',\n // State layer overlay\n 'before:absolute before:inset-0 before:rounded-[inherit] before:bg-current before:opacity-0 before:pointer-events-none',\n 'before:transition-opacity before:duration-100',\n 'hover:before:opacity-[var(--md-sys-state-hover)]',\n 'focus-visible:before:opacity-[var(--md-sys-state-focus)]',\n 'active:before:opacity-[var(--md-sys-state-pressed)]',\n 'data-[pressed]:before:opacity-[var(--md-sys-state-pressed)]',\n // Focus ring (M3: 3px secondary, 2px offset)\n 'focus-visible:outline-[3px] focus-visible:outline-offset-2 focus-visible:outline-secondary',\n // Disabled: no interaction, no state layer, no elevation. Per-variant\n // colors (container on-surface/10, label on-surface-variant/38) live on\n // each variant.\n 'disabled:pointer-events-none disabled:shadow-none disabled:before:opacity-0',\n 'data-[disabled]:pointer-events-none data-[disabled]:shadow-none data-[disabled]:before:opacity-0',\n ],\n variants: {\n // M3 elevation per variant: filled/tonal rest level0→hover level1→pressed level0;\n // elevated rest level1→hover level2→pressed level1. Expressive disabled:\n // container on-surface/10, label on-surface-variant/38 — except tonal, which\n // is unchanged upstream (FilledTonalButtonTokens v0_103) and keeps 0.12 /\n // on-surface. Expressive also moves outlined/text labels to on-surface-variant.\n variant: {\n filled: [\n 'bg-primary text-on-primary',\n 'hover:shadow-level1 focus-visible:shadow-none active:shadow-none data-[pressed]:shadow-none',\n 'disabled:bg-on-surface/10 disabled:text-on-surface-variant/38',\n 'data-[disabled]:bg-on-surface/10 data-[disabled]:text-on-surface-variant/38',\n ],\n tonal: [\n 'bg-secondary-container text-on-secondary-container',\n 'hover:shadow-level1 focus-visible:shadow-none active:shadow-none data-[pressed]:shadow-none',\n 'disabled:bg-on-surface/12 disabled:text-on-surface/38',\n 'data-[disabled]:bg-on-surface/12 data-[disabled]:text-on-surface/38',\n ],\n outlined: [\n 'bg-transparent text-on-surface-variant border border-outline-variant',\n // Compose outlinedButtonBorder(enabled=false) tints the outline with\n // DisabledContainerOpacity (0.1), so the disabled border is faint.\n 'disabled:text-on-surface-variant/38 disabled:border-outline-variant/10',\n 'data-[disabled]:text-on-surface-variant/38 data-[disabled]:border-outline-variant/10',\n ],\n elevated: [\n 'bg-surface-container-low text-primary shadow-level1',\n 'hover:shadow-level2 focus-visible:shadow-level1 active:shadow-level1 data-[pressed]:shadow-level1',\n 'disabled:bg-on-surface/10 disabled:text-on-surface-variant/38',\n 'data-[disabled]:bg-on-surface/10 data-[disabled]:text-on-surface-variant/38',\n ],\n text: [\n 'bg-transparent text-on-surface-variant',\n 'disabled:text-on-surface-variant/38',\n 'data-[disabled]:text-on-surface-variant/38',\n ],\n },\n // Height / horizontal padding / gap / typescale / icon size per Expressive\n // size. The pressed corner morph (PressedContainerShape: XS·S small 8 /\n // M medium 12 / L·XL large 16) rides on data-[pressed]/active here so its\n // attribute-selector specificity wins over the resting `rounded-*`.\n size: {\n xs: [\n // XS is special-cased in Compose Button.kt: contentPaddingFor returns\n // ExtraSmallContentPadding (12dp) and iconSpacingFor returns\n // ExtraSmallIconSpacing (4dp) — tighter than the ButtonXSmallTokens\n // Leading/TrailingSpace (16) and IconLabelSpace (8). S–XL use their tokens.\n 'h-8 px-3 gap-1 text-label-large [&_[data-slot=button-icon]>svg]:size-5',\n 'data-[pressed]:rounded-small active:rounded-small',\n ],\n s: [\n 'h-10 px-4 gap-2 text-label-large [&_[data-slot=button-icon]>svg]:size-5',\n 'data-[pressed]:rounded-small active:rounded-small',\n ],\n m: [\n 'h-14 px-6 gap-2 text-title-medium [&_[data-slot=button-icon]>svg]:size-6',\n 'data-[pressed]:rounded-medium active:rounded-medium',\n ],\n l: [\n 'h-24 px-12 gap-3 text-headline-small [&_[data-slot=button-icon]>svg]:size-8',\n 'data-[pressed]:rounded-large active:rounded-large',\n ],\n xl: [\n 'h-[136px] px-16 gap-4 text-headline-large [&_[data-slot=button-icon]>svg]:size-10',\n 'data-[pressed]:rounded-large active:rounded-large',\n ],\n },\n // round = full pill; the square corner is size-specific (compounds below).\n shape: {\n round: 'rounded-full',\n square: '',\n },\n // Toggle state, string-keyed so a plain (non-toggle) button — `toggle`\n // unset — fires neither compound below (a boolean variant would default to\n // `off` in tailwind-variants and wrongly apply the unselected look).\n toggle: {\n on: '',\n off: '',\n },\n },\n compoundVariants: [\n // ---- Resting square corner (ContainerShapeSquare) ---------------------\n { shape: 'square', size: 'xs', class: 'rounded-medium' }, // 12dp\n { shape: 'square', size: 's', class: 'rounded-medium' }, // 12dp\n { shape: 'square', size: 'm', class: 'rounded-large' }, // 16dp\n { shape: 'square', size: 'l', class: 'rounded-extra-large' }, // 28dp\n { shape: 'square', size: 'xl', class: 'rounded-extra-large' }, // 28dp\n // ---- Selected shape morph: swap to the opposite shape -----------------\n // (listed after the resting corner so tailwind-merge keeps these).\n { shape: 'round', toggle: 'on', size: 'xs', class: 'rounded-medium' },\n { shape: 'round', toggle: 'on', size: 's', class: 'rounded-medium' },\n { shape: 'round', toggle: 'on', size: 'm', class: 'rounded-large' },\n { shape: 'round', toggle: 'on', size: 'l', class: 'rounded-extra-large' },\n { shape: 'round', toggle: 'on', size: 'xl', class: 'rounded-extra-large' },\n { shape: 'square', toggle: 'on', size: 'xs', class: 'rounded-full' },\n { shape: 'square', toggle: 'on', size: 's', class: 'rounded-full' },\n { shape: 'square', toggle: 'on', size: 'm', class: 'rounded-full' },\n { shape: 'square', toggle: 'on', size: 'l', class: 'rounded-full' },\n { shape: 'square', toggle: 'on', size: 'xl', class: 'rounded-full' },\n // ---- Outlined border width (OutlinedOutlineWidth: L 2 / XL 3 dp) ------\n { variant: 'outlined', size: 'l', class: 'border-2' },\n { variant: 'outlined', size: 'xl', class: 'border-[3px]' },\n // ---- Toggle colors (Selected*/Unselected* tokens) ---------------------\n // filled/tonal: base = default & selected look; `toggle:off` = unselected.\n { variant: 'filled', toggle: 'off', class: 'bg-surface-container text-on-surface-variant' },\n { variant: 'tonal', toggle: 'off', class: 'bg-surface-container text-on-surface-variant' },\n // elevated: distinct selected (primary) & unselected looks.\n { variant: 'elevated', toggle: 'on', class: 'bg-primary text-on-primary' },\n {\n variant: 'elevated',\n toggle: 'off',\n class: 'bg-surface-container-low text-on-surface-variant',\n },\n // outlined: selected fills with the inverse surface (base = unselected).\n {\n variant: 'outlined',\n toggle: 'on',\n class: [\n 'bg-inverse-surface text-inverse-on-surface border-transparent',\n 'disabled:bg-on-surface/10 disabled:border-transparent',\n 'data-[disabled]:bg-on-surface/10 data-[disabled]:border-transparent',\n ],\n },\n // text: no Selected/Unselected tokens exist upstream (TextButtonTokens),\n // so selection raises the label emphasis to primary (base = unselected\n // on-surface-variant) to communicate the toggle state.\n { variant: 'text', toggle: 'on', class: 'text-primary' },\n ],\n defaultVariants: {\n variant: 'filled',\n size: 's',\n shape: 'round',\n },\n});\n\nexport const Button = createButton(({ variant, size, shape, selected }) =>\n button({ variant, size, shape, toggle: toToggle(selected) }),\n);\nexport type { ButtonProps, ButtonVariant, ButtonSize, ButtonShape } from '@m3-baseui/core';\n"]}
@@ -20,12 +20,24 @@ var TYPESCALE = [
20
20
  "label-medium",
21
21
  "label-small"
22
22
  ];
23
+ var SHAPE = [
24
+ "none",
25
+ "extra-small",
26
+ "small",
27
+ "medium",
28
+ "large",
29
+ "large-increased",
30
+ "extra-large",
31
+ "extra-large-increased",
32
+ "full"
33
+ ];
23
34
  var tv = (options, config) => tv$1(options, {
24
35
  ...config,
25
36
  twMergeConfig: {
26
37
  extend: {
27
38
  classGroups: {
28
- "font-size": [{ text: [...TYPESCALE] }]
39
+ "font-size": [{ text: [...TYPESCALE] }],
40
+ rounded: [{ rounded: [...SHAPE] }]
29
41
  }
30
42
  }
31
43
  }