@m3-baseui/react-tailwind 1.3.0 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/dialog.d.ts CHANGED
@@ -1,85 +1,115 @@
1
+ import * as _m3_baseui_core from '@m3-baseui/core';
1
2
  import * as react from 'react';
2
3
  import * as _base_ui_react from '@base-ui/react';
3
- import * as tailwind_variants_dist_config_js from 'tailwind-variants/dist/config.js';
4
4
  import * as tailwind_variants from 'tailwind-variants';
5
+ import * as tailwind_variants_dist_config_js from 'tailwind-variants/dist/config.js';
5
6
 
6
7
  declare const dialogTv: tailwind_variants.TVReturnType<{
7
- [key: string]: {
8
- [key: string]: tailwind_variants.ClassValue | {
9
- title?: tailwind_variants.ClassValue;
10
- close?: tailwind_variants.ClassValue;
11
- popup?: tailwind_variants.ClassValue;
12
- description?: tailwind_variants.ClassValue;
13
- backdrop?: tailwind_variants.ClassValue;
8
+ fullscreen: {
9
+ false: {
10
+ popup: string[];
14
11
  };
15
- };
16
- } | {
17
- [x: string]: {
18
- [x: string]: tailwind_variants.ClassValue | {
19
- title?: tailwind_variants.ClassValue;
20
- close?: tailwind_variants.ClassValue;
21
- popup?: tailwind_variants.ClassValue;
22
- description?: tailwind_variants.ClassValue;
23
- backdrop?: tailwind_variants.ClassValue;
12
+ true: {
13
+ popup: string[];
24
14
  };
25
15
  };
26
- } | {}, {
16
+ }, {
27
17
  backdrop: string[];
28
18
  popup: string[];
19
+ header: string[];
20
+ icon: string[];
29
21
  title: string[];
30
22
  description: string[];
23
+ divider: string[];
24
+ actions: string[];
31
25
  close: string[];
32
- }, undefined, tailwind_variants_dist_config_js.TVConfig<unknown, {
33
- [key: string]: {
34
- [key: string]: tailwind_variants.ClassValue | {
35
- title?: tailwind_variants.ClassValue;
36
- close?: tailwind_variants.ClassValue;
37
- popup?: tailwind_variants.ClassValue;
38
- description?: tailwind_variants.ClassValue;
39
- backdrop?: tailwind_variants.ClassValue;
26
+ }, undefined, tailwind_variants_dist_config_js.TVConfig<{
27
+ fullscreen: {
28
+ false: {
29
+ popup: string[];
30
+ };
31
+ true: {
32
+ popup: string[];
40
33
  };
41
34
  };
42
- } | {}>, {
43
- [key: string]: {
44
- [key: string]: tailwind_variants.ClassValue | {
45
- title?: tailwind_variants.ClassValue;
46
- close?: tailwind_variants.ClassValue;
47
- popup?: tailwind_variants.ClassValue;
48
- description?: tailwind_variants.ClassValue;
49
- backdrop?: tailwind_variants.ClassValue;
35
+ }, {
36
+ fullscreen: {
37
+ false: {
38
+ popup: string[];
39
+ };
40
+ true: {
41
+ popup: string[];
42
+ };
43
+ };
44
+ }>, {
45
+ fullscreen: {
46
+ false: {
47
+ popup: string[];
48
+ };
49
+ true: {
50
+ popup: string[];
50
51
  };
51
52
  };
52
- } | {}, {
53
+ }, {
53
54
  backdrop: string[];
54
55
  popup: string[];
56
+ header: string[];
57
+ icon: string[];
55
58
  title: string[];
56
59
  description: string[];
60
+ divider: string[];
61
+ actions: string[];
57
62
  close: string[];
58
- }, tailwind_variants.TVReturnType<unknown, {
63
+ }, tailwind_variants.TVReturnType<{
64
+ fullscreen: {
65
+ false: {
66
+ popup: string[];
67
+ };
68
+ true: {
69
+ popup: string[];
70
+ };
71
+ };
72
+ }, {
59
73
  backdrop: string[];
60
74
  popup: string[];
75
+ header: string[];
76
+ icon: string[];
61
77
  title: string[];
62
78
  description: string[];
79
+ divider: string[];
80
+ actions: string[];
63
81
  close: string[];
64
- }, undefined, tailwind_variants_dist_config_js.TVConfig<unknown, {
65
- [key: string]: {
66
- [key: string]: tailwind_variants.ClassValue | {
67
- title?: tailwind_variants.ClassValue;
68
- close?: tailwind_variants.ClassValue;
69
- popup?: tailwind_variants.ClassValue;
70
- description?: tailwind_variants.ClassValue;
71
- backdrop?: tailwind_variants.ClassValue;
82
+ }, undefined, tailwind_variants_dist_config_js.TVConfig<{
83
+ fullscreen: {
84
+ false: {
85
+ popup: string[];
86
+ };
87
+ true: {
88
+ popup: string[];
89
+ };
90
+ };
91
+ }, {
92
+ fullscreen: {
93
+ false: {
94
+ popup: string[];
95
+ };
96
+ true: {
97
+ popup: string[];
72
98
  };
73
99
  };
74
- } | {}>, unknown, unknown, undefined>>;
100
+ }>, unknown, unknown, undefined>>;
75
101
  declare const Dialog: {
76
102
  Root: typeof _base_ui_react.DialogRoot;
77
103
  Trigger: _base_ui_react.DialogTrigger;
78
104
  Portal: react.ForwardRefExoticComponent<Omit<_base_ui_react.AlertDialogPortalProps, "ref"> & react.RefAttributes<HTMLDivElement>>;
79
105
  Backdrop: react.ForwardRefExoticComponent<Omit<Omit<_base_ui_react.AlertDialogBackdropProps, "ref"> & react.RefAttributes<HTMLDivElement>, "ref"> & react.RefAttributes<unknown>>;
80
- Popup: react.ForwardRefExoticComponent<Omit<Omit<_base_ui_react.AlertDialogPopupProps, "ref"> & react.RefAttributes<HTMLDivElement>, "ref"> & react.RefAttributes<unknown>>;
106
+ Popup: react.ForwardRefExoticComponent<Omit<_m3_baseui_core.DialogPopupOwnProps & Omit<_base_ui_react.AlertDialogPopupProps, "ref"> & react.RefAttributes<HTMLDivElement>, "ref"> & react.RefAttributes<HTMLDivElement>>;
107
+ Icon: react.ForwardRefExoticComponent<react.HTMLAttributes<HTMLSpanElement> & react.RefAttributes<HTMLSpanElement>>;
108
+ Header: react.ForwardRefExoticComponent<react.HTMLAttributes<HTMLDivElement> & react.RefAttributes<HTMLDivElement>>;
81
109
  Title: react.ForwardRefExoticComponent<Omit<Omit<_base_ui_react.AlertDialogTitleProps, "ref"> & react.RefAttributes<HTMLHeadingElement>, "ref"> & react.RefAttributes<unknown>>;
82
110
  Description: react.ForwardRefExoticComponent<Omit<Omit<_base_ui_react.AlertDialogDescriptionProps, "ref"> & react.RefAttributes<HTMLParagraphElement>, "ref"> & react.RefAttributes<unknown>>;
111
+ Divider: react.ForwardRefExoticComponent<react.HTMLAttributes<HTMLHRElement> & react.RefAttributes<HTMLHRElement>>;
112
+ Actions: react.ForwardRefExoticComponent<react.HTMLAttributes<HTMLDivElement> & react.RefAttributes<HTMLDivElement>>;
83
113
  Close: react.ForwardRefExoticComponent<Omit<Omit<_base_ui_react.AlertDialogCloseProps, "ref"> & react.RefAttributes<HTMLButtonElement>, "ref"> & react.RefAttributes<unknown>>;
84
114
  };
85
115
 
package/dist/dialog.js CHANGED
@@ -40,26 +40,61 @@ var dialogTv = tv({
40
40
  "data-[starting-style]:opacity-0 data-[ending-style]:opacity-0"
41
41
  ],
42
42
  popup: [
43
- "fixed left-1/2 top-1/2 z-50 -translate-x-1/2 -translate-y-1/2",
44
- "w-[min(560px,calc(100vw-48px))] max-h-[calc(100vh-48px)] overflow-auto",
45
- "bg-surface-container-high text-on-surface rounded-extra-large shadow-level3",
46
- "p-6 flex flex-col gap-4",
43
+ "fixed z-50 box-border overflow-auto flex flex-col text-on-surface focus:outline-none",
47
44
  "origin-[var(--transform-origin)] transition-[opacity,transform] duration-200 ease-emphasized",
48
- "data-[starting-style]:opacity-0 data-[starting-style]:scale-95",
49
- "data-[ending-style]:opacity-0 data-[ending-style]:scale-95",
50
- "focus:outline-none"
45
+ // Icon present → center the headline + supporting text (M3 hero icon).
46
+ "has-[[data-slot=dialog-icon]]:text-center"
51
47
  ],
48
+ // Fullscreen header row: leading close icon + title (grows, but shrinks +
49
+ // ellipsizes instead of pushing the trailing action off-screen) + action.
50
+ header: [
51
+ "flex items-center gap-2 px-2 h-14 shrink-0",
52
+ "[&>*:nth-child(2)]:grow [&>*:nth-child(2)]:min-w-0 [&>*:nth-child(2)]:overflow-hidden [&>*:nth-child(2)]:text-ellipsis [&>*:nth-child(2)]:whitespace-nowrap"
53
+ ],
54
+ // Centered 24dp hero icon in the secondary color.
55
+ icon: ["inline-flex self-center text-secondary"],
52
56
  title: ["text-headline-small text-on-surface m-0"],
53
57
  description: ["text-body-medium text-on-surface-variant m-0"],
58
+ // 1dp outline-variant rule under the fullscreen header.
59
+ divider: ["h-px w-full bg-outline-variant shrink-0 m-0 border-0"],
60
+ // End-aligned action row: 8dp between buttons; the popup gap (16dp) + mt-2
61
+ // (8dp) totals the 24dp M3 spacing above the actions.
62
+ actions: ["flex justify-end items-center gap-2 mt-2"],
54
63
  close: ["inline-flex"]
64
+ },
65
+ variants: {
66
+ fullscreen: {
67
+ false: {
68
+ popup: [
69
+ "left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2",
70
+ "w-[min(560px,calc(100vw-48px))] min-w-[280px] max-h-[calc(100vh-48px)]",
71
+ "p-6 gap-4 rounded-extra-large bg-surface-container-high shadow-level3",
72
+ "data-[starting-style]:opacity-0 data-[starting-style]:scale-95",
73
+ "data-[ending-style]:opacity-0 data-[ending-style]:scale-95"
74
+ ]
75
+ },
76
+ true: {
77
+ popup: [
78
+ "inset-0 w-screen h-screen max-w-none rounded-none bg-surface",
79
+ "data-[starting-style]:opacity-0 data-[ending-style]:opacity-0"
80
+ ]
81
+ }
82
+ }
83
+ },
84
+ defaultVariants: {
85
+ fullscreen: false
55
86
  }
56
87
  });
57
88
  var d = dialogTv();
58
89
  var Dialog = createDialog({
59
90
  backdrop: d.backdrop(),
60
- popup: d.popup(),
91
+ popup: ({ fullscreen }) => dialogTv({ fullscreen }).popup(),
92
+ header: d.header(),
93
+ icon: d.icon(),
61
94
  title: d.title(),
62
95
  description: d.description(),
96
+ divider: d.divider(),
97
+ actions: d.actions(),
63
98
  close: d.close()
64
99
  });
65
100
 
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/tv.ts","../src/dialog.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,WAAW,EAAA,CAAG;AAAA,EACzB,KAAA,EAAO;AAAA,IACL,QAAA,EAAU;AAAA,MACR,gCAAA;AAAA,MACA,+CAAA;AAAA,MACA;AAAA,KACF;AAAA,IACA,KAAA,EAAO;AAAA,MACL,+DAAA;AAAA,MACA,wEAAA;AAAA,MACA,6EAAA;AAAA,MACA,yBAAA;AAAA,MACA,8FAAA;AAAA,MACA,gEAAA;AAAA,MACA,4DAAA;AAAA,MACA;AAAA,KACF;AAAA,IACA,KAAA,EAAO,CAAC,yCAAyC,CAAA;AAAA,IACjD,WAAA,EAAa,CAAC,8CAA8C,CAAA;AAAA,IAC5D,KAAA,EAAO,CAAC,aAAa;AAAA;AAEzB,CAAC;AAED,IAAM,IAAI,QAAA,EAAS;AACZ,IAAM,SAAS,YAAA,CAAa;AAAA,EACjC,QAAA,EAAU,EAAE,QAAA,EAAS;AAAA,EACrB,KAAA,EAAO,EAAE,KAAA,EAAM;AAAA,EACf,KAAA,EAAO,EAAE,KAAA,EAAM;AAAA,EACf,WAAA,EAAa,EAAE,WAAA,EAAY;AAAA,EAC3B,KAAA,EAAO,EAAE,KAAA;AACX,CAAC","file":"dialog.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 * dialog.ts — Tailwind classes for the M3 basic Dialog.\n *\n * Scrim backdrop + centered surface-container-high popup (extra-large corners,\n * elevation 3) with an emphasized fade/scale transition off Base UI's\n * data-[starting-style] / data-[ending-style] attributes.\n */\nimport { createDialog } from '@m3-baseui/core';\nimport { tv } from './tv';\n\nexport const dialogTv = tv({\n slots: {\n backdrop: [\n 'fixed inset-0 z-40 bg-scrim/32',\n 'transition-opacity duration-200 ease-standard',\n 'data-[starting-style]:opacity-0 data-[ending-style]:opacity-0',\n ],\n popup: [\n 'fixed left-1/2 top-1/2 z-50 -translate-x-1/2 -translate-y-1/2',\n 'w-[min(560px,calc(100vw-48px))] max-h-[calc(100vh-48px)] overflow-auto',\n 'bg-surface-container-high text-on-surface rounded-extra-large shadow-level3',\n 'p-6 flex flex-col gap-4',\n 'origin-[var(--transform-origin)] transition-[opacity,transform] duration-200 ease-emphasized',\n 'data-[starting-style]:opacity-0 data-[starting-style]:scale-95',\n 'data-[ending-style]:opacity-0 data-[ending-style]:scale-95',\n 'focus:outline-none',\n ],\n title: ['text-headline-small text-on-surface m-0'],\n description: ['text-body-medium text-on-surface-variant m-0'],\n close: ['inline-flex'],\n },\n});\n\nconst d = dialogTv();\nexport const Dialog = createDialog({\n backdrop: d.backdrop(),\n popup: d.popup(),\n title: d.title(),\n description: d.description(),\n close: d.close(),\n});\n"]}
1
+ {"version":3,"sources":["../src/tv.ts","../src/dialog.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;;;AC9BI,IAAM,WAAW,EAAA,CAAG;AAAA,EACzB,KAAA,EAAO;AAAA,IACL,QAAA,EAAU;AAAA,MACR,gCAAA;AAAA,MACA,+CAAA;AAAA,MACA;AAAA,KACF;AAAA,IACA,KAAA,EAAO;AAAA,MACL,sFAAA;AAAA,MACA,8FAAA;AAAA;AAAA,MAEA;AAAA,KACF;AAAA;AAAA;AAAA,IAGA,MAAA,EAAQ;AAAA,MACN,4CAAA;AAAA,MACA;AAAA,KACF;AAAA;AAAA,IAEA,IAAA,EAAM,CAAC,wCAAwC,CAAA;AAAA,IAC/C,KAAA,EAAO,CAAC,yCAAyC,CAAA;AAAA,IACjD,WAAA,EAAa,CAAC,8CAA8C,CAAA;AAAA;AAAA,IAE5D,OAAA,EAAS,CAAC,sDAAsD,CAAA;AAAA;AAAA;AAAA,IAGhE,OAAA,EAAS,CAAC,0CAA0C,CAAA;AAAA,IACpD,KAAA,EAAO,CAAC,aAAa;AAAA,GACvB;AAAA,EACA,QAAA,EAAU;AAAA,IACR,UAAA,EAAY;AAAA,MACV,KAAA,EAAO;AAAA,QACL,KAAA,EAAO;AAAA,UACL,oDAAA;AAAA,UACA,wEAAA;AAAA,UACA,uEAAA;AAAA,UACA,gEAAA;AAAA,UACA;AAAA;AACF,OACF;AAAA,MACA,IAAA,EAAM;AAAA,QACJ,KAAA,EAAO;AAAA,UACL,8DAAA;AAAA,UACA;AAAA;AACF;AACF;AACF,GACF;AAAA,EACA,eAAA,EAAiB;AAAA,IACf,UAAA,EAAY;AAAA;AAEhB,CAAC;AAED,IAAM,IAAI,QAAA,EAAS;AACZ,IAAM,SAAS,YAAA,CAAa;AAAA,EACjC,QAAA,EAAU,EAAE,QAAA,EAAS;AAAA,EACrB,KAAA,EAAO,CAAC,EAAE,UAAA,EAAW,KAAM,SAAS,EAAE,UAAA,EAAY,CAAA,CAAE,KAAA,EAAM;AAAA,EAC1D,MAAA,EAAQ,EAAE,MAAA,EAAO;AAAA,EACjB,IAAA,EAAM,EAAE,IAAA,EAAK;AAAA,EACb,KAAA,EAAO,EAAE,KAAA,EAAM;AAAA,EACf,WAAA,EAAa,EAAE,WAAA,EAAY;AAAA,EAC3B,OAAA,EAAS,EAAE,OAAA,EAAQ;AAAA,EACnB,OAAA,EAAS,EAAE,OAAA,EAAQ;AAAA,EACnB,KAAA,EAAO,EAAE,KAAA;AACX,CAAC","file":"dialog.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 * dialog.ts — Tailwind classes for the M3 Dialog (basic + fullscreen).\n *\n * Scrim backdrop + a surface popup with an emphasized fade/scale transition off\n * Base UI's data-[starting-style] / data-[ending-style] attributes. The basic\n * variant is a centered surface-container-high card (extra-large corners,\n * elevation 3, 280–560dp wide); the `fullscreen` variant is an edge-to-edge\n * `surface` with a header row + divider. An optional centered hero icon\n * (`data-slot=\"dialog-icon\"`) center-aligns the headline/supporting text.\n */\nimport { createDialog } from '@m3-baseui/core';\nimport { tv } from './tv';\n\nexport const dialogTv = tv({\n slots: {\n backdrop: [\n 'fixed inset-0 z-40 bg-scrim/32',\n 'transition-opacity duration-200 ease-standard',\n 'data-[starting-style]:opacity-0 data-[ending-style]:opacity-0',\n ],\n popup: [\n 'fixed z-50 box-border overflow-auto flex flex-col text-on-surface focus:outline-none',\n 'origin-[var(--transform-origin)] transition-[opacity,transform] duration-200 ease-emphasized',\n // Icon present → center the headline + supporting text (M3 hero icon).\n 'has-[[data-slot=dialog-icon]]:text-center',\n ],\n // Fullscreen header row: leading close icon + title (grows, but shrinks +\n // ellipsizes instead of pushing the trailing action off-screen) + action.\n header: [\n 'flex items-center gap-2 px-2 h-14 shrink-0',\n '[&>*:nth-child(2)]:grow [&>*:nth-child(2)]:min-w-0 [&>*:nth-child(2)]:overflow-hidden [&>*:nth-child(2)]:text-ellipsis [&>*:nth-child(2)]:whitespace-nowrap',\n ],\n // Centered 24dp hero icon in the secondary color.\n icon: ['inline-flex self-center text-secondary'],\n title: ['text-headline-small text-on-surface m-0'],\n description: ['text-body-medium text-on-surface-variant m-0'],\n // 1dp outline-variant rule under the fullscreen header.\n divider: ['h-px w-full bg-outline-variant shrink-0 m-0 border-0'],\n // End-aligned action row: 8dp between buttons; the popup gap (16dp) + mt-2\n // (8dp) totals the 24dp M3 spacing above the actions.\n actions: ['flex justify-end items-center gap-2 mt-2'],\n close: ['inline-flex'],\n },\n variants: {\n fullscreen: {\n false: {\n popup: [\n 'left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2',\n 'w-[min(560px,calc(100vw-48px))] min-w-[280px] max-h-[calc(100vh-48px)]',\n 'p-6 gap-4 rounded-extra-large bg-surface-container-high shadow-level3',\n 'data-[starting-style]:opacity-0 data-[starting-style]:scale-95',\n 'data-[ending-style]:opacity-0 data-[ending-style]:scale-95',\n ],\n },\n true: {\n popup: [\n 'inset-0 w-screen h-screen max-w-none rounded-none bg-surface',\n 'data-[starting-style]:opacity-0 data-[ending-style]:opacity-0',\n ],\n },\n },\n },\n defaultVariants: {\n fullscreen: false,\n },\n});\n\nconst d = dialogTv();\nexport const Dialog = createDialog({\n backdrop: d.backdrop(),\n popup: ({ fullscreen }) => dialogTv({ fullscreen }).popup(),\n header: d.header(),\n icon: d.icon(),\n title: d.title(),\n description: d.description(),\n divider: d.divider(),\n actions: d.actions(),\n close: d.close(),\n});\n"]}
package/dist/index.d.ts CHANGED
@@ -4,7 +4,7 @@ export { Switch, switchTv } from './switch.js';
4
4
  export { Checkbox, checkboxTv } from './checkbox.js';
5
5
  export { Radio, RadioGroup, radioTv } from './radio.js';
6
6
  export { Chip, chipTv } from './chip.js';
7
- export { Tooltip, tooltipTv } from './tooltip.js';
7
+ export { RichTooltip, Tooltip, richTooltipTv, tooltipTv } from './tooltip.js';
8
8
  export { Dialog, dialogTv } from './dialog.js';
9
9
  export { Menu, menuTv } from './menu.js';
10
10
  export { Tabs, tabsTv } from './tabs.js';
@@ -34,7 +34,7 @@ export { SideSheet, sideSheetTv } from './side-sheet.js';
34
34
  export { Search, searchTv } from './search.js';
35
35
  export { DatePicker, datePickerTv } from './date-picker.js';
36
36
  export { TimePicker, timePickerTv } from './time-picker.js';
37
- export { BadgeProps, BadgeSize, BottomAppBarProps, BottomSheetVariant, ButtonGroupProps, ButtonGroupVariant, ButtonProps, ButtonVariant, CardProps, CardVariant, CarouselVariant, ChipProps, ChipVariant, CircularProgressProps, ContrastLevel, DividerInset, DividerOrientation, DividerProps, FabColor, FabMenuItemProps, FabMenuTriggerProps, FabProps, FabSize, IconButtonProps, IconButtonVariant, ItemProps, LinearProgressProps, ListItemLines, ListItemProps, LoadingIndicatorProps, NavigationDrawerVariant, Ripple, SchemeVariant, SideSheetSide, SideSheetVariant, TabsVariant, TextFieldProps, TextFieldVariant, ThemeMode, ThemeProvider, ThemeProviderProps, TimePickerVariant, TimeValue, ToolbarOrientation, ToolbarProps, ToolbarVariant, TopAppBarProps, TopAppBarVariant, applyScheme, generateScheme, schemeToCssText, useSnackbar, useTheme } from '@m3-baseui/core';
37
+ export { BadgeProps, BadgeSize, BottomAppBarProps, BottomSheetVariant, ButtonGroupProps, ButtonGroupVariant, ButtonProps, ButtonVariant, CardProps, CardVariant, CarouselVariant, ChipProps, ChipVariant, CircularProgressProps, ContrastLevel, DividerInset, DividerOrientation, DividerProps, FabColor, FabMenuItemProps, FabMenuTriggerProps, FabProps, FabSize, ITEM_LEADING_VARIANTS, IconButtonProps, IconButtonVariant, ItemLeadingVariant, ItemProps, LIST_LEADING_VARIANTS, LinearProgressProps, ListItemLines, ListItemProps, ListLeadingVariant, LoadingIndicatorProps, NavigationDrawerVariant, Ripple, SchemeVariant, SideSheetSide, SideSheetVariant, TabsVariant, TextFieldProps, TextFieldVariant, ThemeMode, ThemeProvider, ThemeProviderProps, TimePickerVariant, TimeValue, ToolbarOrientation, ToolbarProps, ToolbarVariant, TopAppBarProps, TopAppBarVariant, applyScheme, generateScheme, schemeToCssText, useSnackbar, useTheme } from '@m3-baseui/core';
38
38
  export { Toolbar, toolbarTv } from './toolbar.js';
39
39
  export { Carousel, carouselTv } from './carousel.js';
40
40
  import '@base-ui/react';
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use client";
2
- import { createButton, createIconButton, createSwitch, createCheckbox, createRadio, createRadioGroup, createChip, createTooltip, createDialog, createMenu, createTabs, createSlider, createSelect, createTextField, createNavigationBar, createFab, createFabMenu, createDivider, createProgress, createLoadingIndicator, createList, createSnackbar, createItem, createBadge, createCard, createSegmentedButton, createButtonGroup, createSplitButton, createNavigationDrawer, createTopAppBar, createBottomAppBar, createNavigationRail, createBottomSheet, createSideSheet, createSearch, createDatePicker, createTimePicker, createToolbar, createCarousel } from '@m3-baseui/core';
3
- export { Ripple, ThemeProvider, applyScheme, generateScheme, schemeToCssText, useSnackbar, useTheme } from '@m3-baseui/core';
2
+ import { createButton, createIconButton, createSwitch, createCheckbox, createRadio, createRadioGroup, createChip, createTooltip, createRichTooltip, createDialog, createMenu, createTabs, createSlider, createSelect, createTextField, createNavigationBar, createFab, createFabMenu, createDivider, createProgress, createLoadingIndicator, createList, createSnackbar, createItem, createBadge, createCard, createSegmentedButton, createButtonGroup, createSplitButton, createNavigationDrawer, createTopAppBar, createBottomAppBar, createNavigationRail, createBottomSheet, createSideSheet, createSearch, createDatePicker, createTimePicker, createToolbar, createCarousel } from '@m3-baseui/core';
3
+ export { ITEM_LEADING_VARIANTS, LIST_LEADING_VARIANTS, Ripple, ThemeProvider, applyScheme, generateScheme, schemeToCssText, useSnackbar, useTheme } from '@m3-baseui/core';
4
4
  import { tv } from 'tailwind-variants';
5
5
 
6
6
  // src/button.ts
@@ -466,20 +466,48 @@ var tv7 = (options, config) => tv(options, {
466
466
  });
467
467
 
468
468
  // src/tooltip.ts
469
+ var transition = [
470
+ "origin-[var(--transform-origin)] transition-[opacity,transform] duration-150 ease-standard",
471
+ "data-[starting-style]:opacity-0 data-[starting-style]:scale-95",
472
+ "data-[ending-style]:opacity-0 data-[ending-style]:scale-95"
473
+ ];
469
474
  var tooltipTv = tv7({
470
475
  slots: {
471
476
  popup: [
472
477
  "bg-inverse-surface text-inverse-on-surface text-body-small",
473
478
  "rounded-extra-small px-2 py-1 max-w-[224px] select-none",
474
- "origin-[var(--transform-origin)] transition-[opacity,transform] duration-150 ease-standard",
475
- "data-[starting-style]:opacity-0 data-[starting-style]:scale-95",
476
- "data-[ending-style]:opacity-0 data-[ending-style]:scale-95"
479
+ ...transition
477
480
  ],
478
481
  arrow: ["text-inverse-surface"]
479
482
  }
480
483
  });
484
+ var richTooltipTv = tv7({
485
+ slots: {
486
+ popup: [
487
+ "bg-surface-container text-on-surface shadow-level2",
488
+ "rounded-medium px-4 py-3 max-w-[320px] flex flex-col gap-1",
489
+ "outline-none",
490
+ ...transition
491
+ ],
492
+ arrow: ["text-surface-container"],
493
+ subhead: ["text-title-small text-on-surface m-0"],
494
+ supportingText: ["text-body-medium text-on-surface-variant m-0"],
495
+ // M3 places rich-tooltip actions at the bottom-left (leading), not trailing
496
+ // like a dialog. -ml-2 pulls the text button so its label optically aligns
497
+ // with the content's left edge.
498
+ actions: ["flex flex-wrap items-center gap-2 mt-1 -ml-2"]
499
+ }
500
+ });
481
501
  var t = tooltipTv();
482
502
  var Tooltip = createTooltip({ popup: t.popup(), arrow: t.arrow() });
503
+ var r2 = richTooltipTv();
504
+ var RichTooltip = createRichTooltip({
505
+ popup: r2.popup(),
506
+ arrow: r2.arrow(),
507
+ subhead: r2.subhead(),
508
+ supportingText: r2.supportingText(),
509
+ actions: r2.actions()
510
+ });
483
511
  var dialogTv = tv7({
484
512
  slots: {
485
513
  backdrop: [
@@ -488,26 +516,61 @@ var dialogTv = tv7({
488
516
  "data-[starting-style]:opacity-0 data-[ending-style]:opacity-0"
489
517
  ],
490
518
  popup: [
491
- "fixed left-1/2 top-1/2 z-50 -translate-x-1/2 -translate-y-1/2",
492
- "w-[min(560px,calc(100vw-48px))] max-h-[calc(100vh-48px)] overflow-auto",
493
- "bg-surface-container-high text-on-surface rounded-extra-large shadow-level3",
494
- "p-6 flex flex-col gap-4",
519
+ "fixed z-50 box-border overflow-auto flex flex-col text-on-surface focus:outline-none",
495
520
  "origin-[var(--transform-origin)] transition-[opacity,transform] duration-200 ease-emphasized",
496
- "data-[starting-style]:opacity-0 data-[starting-style]:scale-95",
497
- "data-[ending-style]:opacity-0 data-[ending-style]:scale-95",
498
- "focus:outline-none"
521
+ // Icon present → center the headline + supporting text (M3 hero icon).
522
+ "has-[[data-slot=dialog-icon]]:text-center"
523
+ ],
524
+ // Fullscreen header row: leading close icon + title (grows, but shrinks +
525
+ // ellipsizes instead of pushing the trailing action off-screen) + action.
526
+ header: [
527
+ "flex items-center gap-2 px-2 h-14 shrink-0",
528
+ "[&>*:nth-child(2)]:grow [&>*:nth-child(2)]:min-w-0 [&>*:nth-child(2)]:overflow-hidden [&>*:nth-child(2)]:text-ellipsis [&>*:nth-child(2)]:whitespace-nowrap"
499
529
  ],
530
+ // Centered 24dp hero icon in the secondary color.
531
+ icon: ["inline-flex self-center text-secondary"],
500
532
  title: ["text-headline-small text-on-surface m-0"],
501
533
  description: ["text-body-medium text-on-surface-variant m-0"],
534
+ // 1dp outline-variant rule under the fullscreen header.
535
+ divider: ["h-px w-full bg-outline-variant shrink-0 m-0 border-0"],
536
+ // End-aligned action row: 8dp between buttons; the popup gap (16dp) + mt-2
537
+ // (8dp) totals the 24dp M3 spacing above the actions.
538
+ actions: ["flex justify-end items-center gap-2 mt-2"],
502
539
  close: ["inline-flex"]
540
+ },
541
+ variants: {
542
+ fullscreen: {
543
+ false: {
544
+ popup: [
545
+ "left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2",
546
+ "w-[min(560px,calc(100vw-48px))] min-w-[280px] max-h-[calc(100vh-48px)]",
547
+ "p-6 gap-4 rounded-extra-large bg-surface-container-high shadow-level3",
548
+ "data-[starting-style]:opacity-0 data-[starting-style]:scale-95",
549
+ "data-[ending-style]:opacity-0 data-[ending-style]:scale-95"
550
+ ]
551
+ },
552
+ true: {
553
+ popup: [
554
+ "inset-0 w-screen h-screen max-w-none rounded-none bg-surface",
555
+ "data-[starting-style]:opacity-0 data-[ending-style]:opacity-0"
556
+ ]
557
+ }
558
+ }
559
+ },
560
+ defaultVariants: {
561
+ fullscreen: false
503
562
  }
504
563
  });
505
564
  var d = dialogTv();
506
565
  var Dialog = createDialog({
507
566
  backdrop: d.backdrop(),
508
- popup: d.popup(),
567
+ popup: ({ fullscreen }) => dialogTv({ fullscreen }).popup(),
568
+ header: d.header(),
569
+ icon: d.icon(),
509
570
  title: d.title(),
510
571
  description: d.description(),
572
+ divider: d.divider(),
573
+ actions: d.actions(),
511
574
  close: d.close()
512
575
  });
513
576
  var menuTv = tv7({
@@ -990,8 +1053,29 @@ var dividerTv = tv({
990
1053
  var Divider = createDivider(({ inset, orientation }) => dividerTv({ inset, orientation }));
991
1054
  var linearTv = tv({
992
1055
  slots: {
993
- root: "group relative block w-full h-1 overflow-hidden rounded-full",
994
- track: "absolute inset-0 bg-surface-container-highest rounded-full",
1056
+ // The track-stop dot (4dp, primary) sits at the inline-end via `after:`. It's
1057
+ // a determinate-only M3 concept, so it's hidden while indeterminate. Logical
1058
+ // `end-0` mirrors with the indicator under `dir="rtl"`.
1059
+ root: [
1060
+ "group relative block w-full h-1 overflow-hidden rounded-full",
1061
+ "after:content-[''] after:absolute after:end-0 after:top-1/2 after:-translate-y-1/2",
1062
+ "after:size-1 after:rounded-full after:bg-primary",
1063
+ // Self variant (not `group-data-*`): the dot is on the root element itself,
1064
+ // which carries `data-indeterminate` — it isn't a descendant of `.group`.
1065
+ "data-[indeterminate]:after:hidden"
1066
+ ],
1067
+ // Positioning container only; the inactive track is the `before:` pseudo so a
1068
+ // 4dp gap separates it from the active indicator (`--m3-progress` + 4px). The
1069
+ // gap uses logical inline insets so it tracks the indicator (which Base UI
1070
+ // anchors at inline-start) under `dir="rtl"`. Indeterminate has no fraction,
1071
+ // so the inactive track spans the full width.
1072
+ track: [
1073
+ "absolute inset-0",
1074
+ "before:content-[''] before:absolute before:inset-y-0 before:end-0",
1075
+ "before:[inset-inline-start:calc(var(--m3-progress,0%)+4px)]",
1076
+ "before:bg-surface-container-highest before:rounded-full",
1077
+ "group-data-[indeterminate]:before:start-0"
1078
+ ],
995
1079
  indicator: [
996
1080
  "absolute inset-y-0 left-0 bg-primary rounded-full",
997
1081
  "transition-[width] duration-200 ease-standard",
@@ -1050,7 +1134,14 @@ var listTv = tv7({
1050
1134
  "group relative flex w-full items-center gap-4 box-border px-4 text-left",
1051
1135
  "bg-transparent border-0 text-on-surface no-underline"
1052
1136
  ],
1053
- leading: "flex items-center justify-center shrink-0 text-on-surface-variant [&_svg]:size-6",
1137
+ leading: [
1138
+ "flex items-center justify-center shrink-0 overflow-hidden text-on-surface-variant",
1139
+ "[&_svg]:size-6 [&_img]:size-full [&_img]:object-cover",
1140
+ // M3 leading column widths, keyed on the factory's data-leading attribute.
1141
+ "data-[leading=avatar]:size-10 data-[leading=avatar]:rounded-full",
1142
+ "data-[leading=image]:size-14",
1143
+ "data-[leading=video]:w-25 data-[leading=video]:h-14"
1144
+ ],
1054
1145
  content: "flex flex-col min-w-0 flex-1",
1055
1146
  headline: "text-body-large text-on-surface group-data-[disabled]:text-on-surface/38",
1056
1147
  supporting: "text-body-medium text-on-surface-variant group-data-[disabled]:text-on-surface/38",
@@ -1103,10 +1194,15 @@ var snackbarTv = tv({
1103
1194
  slots: {
1104
1195
  viewport: [
1105
1196
  "fixed bottom-4 left-1/2 -translate-x-1/2 z-50",
1106
- "flex flex-col gap-2 w-[min(560px,calc(100vw-32px))]"
1197
+ // M3 container width: cap at 672dp, clamp to the viewport on small screens.
1198
+ // Center items so content-following (w-fit) snackbars stay under the anchor.
1199
+ "flex flex-col items-center gap-2 w-[calc(100vw-32px)] max-w-[672px]"
1107
1200
  ],
1108
1201
  root: [
1109
1202
  "relative flex items-center gap-2 min-h-12 box-border pl-4 pr-2 py-2",
1203
+ // M3 container width follows content within min 344dp / max 672dp. The
1204
+ // min is clamped by 100% so it never overflows a narrower viewport.
1205
+ "w-fit min-w-[min(344px,100%)] max-w-[672px]",
1110
1206
  "rounded-extra-small bg-inverse-surface text-inverse-on-surface shadow-level3",
1111
1207
  "text-body-medium",
1112
1208
  "transition-[opacity,transform] duration-200 ease-emphasized",
@@ -1152,7 +1248,14 @@ var itemTv = tv7({
1152
1248
  "relative flex w-full items-center gap-4 box-border px-4 py-3 min-h-14 text-left",
1153
1249
  "bg-transparent text-on-surface"
1154
1250
  ],
1155
- leading: "flex items-center justify-center shrink-0 text-on-surface-variant [&_svg]:size-6",
1251
+ leading: [
1252
+ "flex items-center justify-center shrink-0 overflow-hidden text-on-surface-variant",
1253
+ "[&_svg]:size-6 [&_img]:size-full [&_img]:object-cover",
1254
+ // M3 leading column widths, keyed on the factory's data-leading attribute.
1255
+ "data-[leading=avatar]:size-10 data-[leading=avatar]:rounded-full",
1256
+ "data-[leading=image]:size-14",
1257
+ "data-[leading=video]:w-25 data-[leading=video]:h-14"
1258
+ ],
1156
1259
  content: "flex flex-col min-w-0 flex-1",
1157
1260
  overline: "text-label-small text-on-surface-variant",
1158
1261
  headline: "text-body-large text-on-surface",
@@ -1876,6 +1979,6 @@ var Carousel = createCarousel((variant) => {
1876
1979
  return { root: s14.root(), item: s14.item() };
1877
1980
  });
1878
1981
 
1879
- export { Badge, BottomAppBar, BottomSheet, Button, ButtonGroup, Card, Carousel, Checkbox, Chip, DatePicker, Dialog, Divider, Fab, FabMenu, IconButton, Item, List, LoadingIndicator, Menu, NavigationBar, NavigationDrawer, NavigationRail, Progress, Radio, RadioGroup, Search, SegmentedButton, Select, SideSheet, Slider, Snackbar, SplitButton, Switch, Tabs, TextField, TimePicker, Toolbar, Tooltip, TopAppBar, badgeTv, bottomAppBarTv, bottomSheetTv, button, buttonGroup, cardTv, carouselTv, checkboxTv, chipTv, circularTv, datePickerTv, dialogTv, dividerTv, fabMenuTv, fabTv, iconButton, itemTv, linearTv, listTv, loadingIndicatorTv, menuTv, navigationBarTv, navigationDrawerTv, navigationRailTv, radioTv, searchTv, segmentedButtonTv, selectTv, sideSheetTv, sliderTv, snackbarTv, splitButtonTv, switchTv, tabsTv, textFieldTv, timePickerTv, toolbarTv, tooltipTv, topAppBarTv };
1982
+ export { Badge, BottomAppBar, BottomSheet, Button, ButtonGroup, Card, Carousel, Checkbox, Chip, DatePicker, Dialog, Divider, Fab, FabMenu, IconButton, Item, List, LoadingIndicator, Menu, NavigationBar, NavigationDrawer, NavigationRail, Progress, Radio, RadioGroup, RichTooltip, Search, SegmentedButton, Select, SideSheet, Slider, Snackbar, SplitButton, Switch, Tabs, TextField, TimePicker, Toolbar, Tooltip, TopAppBar, badgeTv, bottomAppBarTv, bottomSheetTv, button, buttonGroup, cardTv, carouselTv, checkboxTv, chipTv, circularTv, datePickerTv, dialogTv, dividerTv, fabMenuTv, fabTv, iconButton, itemTv, linearTv, listTv, loadingIndicatorTv, menuTv, navigationBarTv, navigationDrawerTv, navigationRailTv, radioTv, richTooltipTv, searchTv, segmentedButtonTv, selectTv, sideSheetTv, sliderTv, snackbarTv, splitButtonTv, switchTv, tabsTv, textFieldTv, timePickerTv, toolbarTv, tooltipTv, topAppBarTv };
1880
1983
  //# sourceMappingURL=index.js.map
1881
1984
  //# sourceMappingURL=index.js.map