@nucleux/md3-personality 0.8.0 → 0.10.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/index.cjs +106 -42
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +6 -3
- package/dist/index.d.ts +6 -3
- package/dist/index.js +107 -43
- package/dist/index.js.map +1 -1
- package/package.json +6 -3
package/dist/index.cjs
CHANGED
|
@@ -30,7 +30,8 @@ var React__namespace = /*#__PURE__*/_interopNamespace(React);
|
|
|
30
30
|
// src/index.tsx
|
|
31
31
|
var stateLayer = "relative overflow-hidden before:absolute before:inset-0 before:bg-current before:opacity-0 before:transition-opacity before:content-[''] hover:before:opacity-[0.08] focus-visible:before:opacity-[0.12] active:before:opacity-[0.12] motion-reduce:before:transition-none";
|
|
32
32
|
var Md3Personality = React__namespace.forwardRef(
|
|
33
|
-
({ options = personality.defaultTones, value, defaultValue, onValueChange, label = "Tone", className, ...props }, ref) => {
|
|
33
|
+
({ options = personality.defaultTones, value, defaultValue, onValueChange, label = "Tone", variant = "chips", note, className, ...props }, ref) => {
|
|
34
|
+
const list = variant === "list";
|
|
34
35
|
const [internal, setInternal] = React__namespace.useState(defaultValue);
|
|
35
36
|
const current = value !== void 0 ? value : internal;
|
|
36
37
|
const refs = React__namespace.useRef([]);
|
|
@@ -53,47 +54,110 @@ var Md3Personality = React__namespace.forwardRef(
|
|
|
53
54
|
refs.current[next]?.focus();
|
|
54
55
|
select(options[next].value);
|
|
55
56
|
};
|
|
56
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
57
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
58
|
+
"div",
|
|
59
|
+
{
|
|
60
|
+
ref,
|
|
61
|
+
"data-variant": "tone-matrix",
|
|
62
|
+
"data-layout": variant,
|
|
63
|
+
className: utils.cn("flex flex-col gap-2", className),
|
|
64
|
+
...props,
|
|
65
|
+
children: [
|
|
66
|
+
label && /* @__PURE__ */ jsxRuntime.jsx(
|
|
67
|
+
"span",
|
|
68
|
+
{
|
|
69
|
+
className: list ? "text-lg font-semibold text-md-on-surface" : "text-xs font-medium tracking-[0.5px] text-md-on-surface-variant",
|
|
70
|
+
children: label
|
|
71
|
+
}
|
|
72
|
+
),
|
|
73
|
+
note && /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "m-0 mt-2 flex items-center gap-1.5 text-sm tracking-[0.25px] text-md-on-surface-variant", children: [
|
|
74
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Lock, { "aria-hidden": "true", className: "size-4 shrink-0" }),
|
|
75
|
+
note
|
|
76
|
+
] }),
|
|
77
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
78
|
+
"div",
|
|
79
|
+
{
|
|
80
|
+
role: "radiogroup",
|
|
81
|
+
"aria-label": typeof label === "string" ? label : "Tone",
|
|
82
|
+
className: list ? "mt-2 flex flex-col" : "flex flex-wrap gap-2",
|
|
83
|
+
children: options.map((option, index) => {
|
|
84
|
+
const active = current === option.value;
|
|
85
|
+
if (list) {
|
|
86
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
87
|
+
"button",
|
|
88
|
+
{
|
|
89
|
+
ref: (el) => {
|
|
90
|
+
refs.current[index] = el;
|
|
91
|
+
},
|
|
92
|
+
type: "button",
|
|
93
|
+
role: "radio",
|
|
94
|
+
"aria-checked": active,
|
|
95
|
+
"aria-describedby": option.description ? `${descId}-${index}` : void 0,
|
|
96
|
+
tabIndex: index === tabStop ? 0 : -1,
|
|
97
|
+
onClick: () => select(option.value),
|
|
98
|
+
onKeyDown: (e) => onKeyDown(e, index),
|
|
99
|
+
className: utils.cn(
|
|
100
|
+
"flex items-start gap-4 rounded-md-md py-2 pl-2.5 pr-3 text-left outline-none focus-visible:ring-2 focus-visible:ring-md-primary",
|
|
101
|
+
stateLayer
|
|
102
|
+
),
|
|
103
|
+
children: [
|
|
104
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
105
|
+
"span",
|
|
106
|
+
{
|
|
107
|
+
"aria-hidden": "true",
|
|
108
|
+
className: utils.cn(
|
|
109
|
+
"relative mt-0.5 grid size-5 shrink-0 place-items-center rounded-full border-2 transition-colors motion-reduce:transition-none",
|
|
110
|
+
active ? "border-md-primary" : "border-md-on-surface-variant"
|
|
111
|
+
),
|
|
112
|
+
children: active && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "size-2.5 rounded-full bg-md-primary" })
|
|
113
|
+
}
|
|
114
|
+
),
|
|
115
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "relative flex flex-col gap-1", children: [
|
|
116
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-center gap-2 text-base text-md-on-surface", children: [
|
|
117
|
+
option.icon,
|
|
118
|
+
option.label,
|
|
119
|
+
option.badge != null && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "rounded-md-sm bg-md-primary-container px-1.5 py-0.5 text-xs font-semibold tracking-[0.5px] text-md-on-primary-container", children: option.badge })
|
|
120
|
+
] }),
|
|
121
|
+
option.description && /* @__PURE__ */ jsxRuntime.jsx("span", { id: `${descId}-${index}`, className: "text-sm tracking-[0.25px] text-md-on-surface-variant", children: option.description })
|
|
122
|
+
] })
|
|
123
|
+
]
|
|
124
|
+
},
|
|
125
|
+
option.value
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
129
|
+
"button",
|
|
130
|
+
{
|
|
131
|
+
ref: (el) => {
|
|
132
|
+
refs.current[index] = el;
|
|
133
|
+
},
|
|
134
|
+
type: "button",
|
|
135
|
+
role: "radio",
|
|
136
|
+
"aria-checked": active,
|
|
137
|
+
"aria-describedby": option.description ? `${descId}-${index}` : void 0,
|
|
138
|
+
tabIndex: index === tabStop ? 0 : -1,
|
|
139
|
+
onClick: () => select(option.value),
|
|
140
|
+
onKeyDown: (e) => onKeyDown(e, index),
|
|
141
|
+
className: utils.cn(
|
|
142
|
+
"inline-flex h-8 items-center gap-2 rounded-md-sm border px-3 text-sm font-medium tracking-[0.1px] outline-none transition-colors focus-visible:ring-2 focus-visible:ring-md-primary motion-reduce:transition-none [&_svg]:relative [&_svg]:size-[18px]",
|
|
143
|
+
stateLayer,
|
|
144
|
+
active ? "border-transparent bg-md-secondary-container pl-2 text-md-on-secondary-container" : "border-md-outline bg-transparent text-md-on-surface-variant"
|
|
145
|
+
),
|
|
146
|
+
children: [
|
|
147
|
+
active && option.icon == null && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { "aria-hidden": "true" }),
|
|
148
|
+
option.icon,
|
|
149
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "relative", children: option.label }),
|
|
150
|
+
option.description && /* @__PURE__ */ jsxRuntime.jsx("span", { id: `${descId}-${index}`, className: "sr-only", children: option.description })
|
|
151
|
+
]
|
|
152
|
+
},
|
|
153
|
+
option.value
|
|
154
|
+
);
|
|
155
|
+
})
|
|
156
|
+
}
|
|
157
|
+
)
|
|
158
|
+
]
|
|
159
|
+
}
|
|
160
|
+
);
|
|
97
161
|
}
|
|
98
162
|
);
|
|
99
163
|
Md3Personality.displayName = "Md3Personality";
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.tsx"],"names":["React","defaultTones","jsxs","cn","jsx","Check","Lock"],"mappings":"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","file":"index.cjs","sourcesContent":["import * as React from \"react\";\nimport { Check, Lock } from \"lucide-react\";\nimport { cn } from \"@nucleux/utils\";\nimport { defaultTones } from \"@nucleux/personality\";\nimport type {\n PersonalityProps,\n PersonalitySampleDialogProps,\n PersonalityVoiceCardProps,\n} from \"@nucleux/personality\";\n\nexport type { ToneOption, PersonalitySampleTurn } from \"@nucleux/personality\";\nexport { defaultTones } from \"@nucleux/personality\";\nexport type Md3PersonalityProps = PersonalityProps;\nexport type Md3PersonalityVoiceCardProps = PersonalityVoiceCardProps;\nexport type Md3PersonalitySampleDialogProps = PersonalitySampleDialogProps;\n\nconst stateLayer =\n \"relative overflow-hidden before:absolute before:inset-0 before:bg-current before:opacity-0 before:transition-opacity before:content-[''] hover:before:opacity-[0.08] focus-visible:before:opacity-[0.12] active:before:opacity-[0.12] motion-reduce:before:transition-none\";\n\n/**\n * The `tone-matrix` in Material 3 — the twin of `Personality`, with the same\n * API and keyboard model. A small set of writing styles as M3 filter chips:\n * the selected one takes the secondary-container role and a leading check;\n * hover, focus and press are the chip's 8% / 12% state layer. It is a radio\n * group with roving focus (arrow keys move and select, Home / End jump).\n * Tone changes how the agent writes, never what it may do — keep\n * permission, caveat and refusal strings outside it.\n */\nexport const Md3Personality = React.forwardRef<HTMLDivElement, Md3PersonalityProps>(\n ({ options = defaultTones, value, defaultValue, onValueChange, label = \"Tone\", className, ...props }, ref) => {\n // Selection and roving-focus logic copied from @nucleux/personality (internal there).\n const [internal, setInternal] = React.useState<string | undefined>(defaultValue);\n const current = value !== undefined ? value : internal;\n const refs = React.useRef<(HTMLButtonElement | null)[]>([]);\n const descId = React.useId();\n const select = (next: string) => {\n if (value === undefined) setInternal(next);\n onValueChange?.(next);\n };\n const selectedIndex = options.findIndex((o) => o.value === current);\n const tabStop = selectedIndex >= 0 ? selectedIndex : 0;\n\n const onKeyDown = (e: React.KeyboardEvent, index: number) => {\n const last = options.length - 1;\n let next: number | null = null;\n if (e.key === \"ArrowRight\" || e.key === \"ArrowDown\") next = index === last ? 0 : index + 1;\n else if (e.key === \"ArrowLeft\" || e.key === \"ArrowUp\") next = index === 0 ? last : index - 1;\n else if (e.key === \"Home\") next = 0;\n else if (e.key === \"End\") next = last;\n if (next === null) return;\n e.preventDefault();\n refs.current[next]?.focus();\n select(options[next]!.value);\n };\n\n return (\n <div ref={ref} data-variant=\"tone-matrix\" className={cn(\"flex flex-col gap-2\", className)} {...props}>\n {label && (\n <span className=\"text-xs font-medium tracking-[0.5px] text-md-on-surface-variant\">{label}</span>\n )}\n <div\n role=\"radiogroup\"\n aria-label={typeof label === \"string\" ? label : \"Tone\"}\n className=\"flex flex-wrap gap-2\"\n >\n {options.map((option, index) => {\n const active = current === option.value;\n return (\n <button\n key={option.value}\n ref={(el) => {\n refs.current[index] = el;\n }}\n type=\"button\"\n role=\"radio\"\n aria-checked={active}\n aria-describedby={option.description ? `${descId}-${index}` : undefined}\n tabIndex={index === tabStop ? 0 : -1}\n onClick={() => select(option.value)}\n onKeyDown={(e) => onKeyDown(e, index)}\n className={cn(\n \"inline-flex h-8 items-center gap-2 rounded-md-sm border px-3 text-sm font-medium tracking-[0.1px] outline-none transition-colors focus-visible:ring-2 focus-visible:ring-md-primary motion-reduce:transition-none [&_svg]:relative [&_svg]:size-[18px]\",\n stateLayer,\n active\n ? \"border-transparent bg-md-secondary-container pl-2 text-md-on-secondary-container\"\n : \"border-md-outline bg-transparent text-md-on-surface-variant\",\n )}\n >\n {active && option.icon == null && <Check aria-hidden=\"true\" />}\n {option.icon}\n <span className=\"relative\">{option.label}</span>\n {option.description && (\n <span id={`${descId}-${index}`} className=\"sr-only\">\n {option.description}\n </span>\n )}\n </button>\n );\n })}\n </div>\n </div>\n );\n },\n);\nMd3Personality.displayName = \"Md3Personality\";\n\n/**\n * The `voice-card` in Material 3 — the twin of `PersonalityVoiceCard`. An\n * outlined card whose sample utterance sits on a surface-container ground\n * behind a primary rule (the voice, written down), with the voice tags as\n * outlined chips beneath it.\n */\nexport const Md3PersonalityVoiceCard = React.forwardRef<HTMLElement, Md3PersonalityVoiceCardProps>(\n ({ quote, tags = [], label = \"Voice\", className, ...props }, ref) => (\n <figure\n ref={ref}\n aria-label={label}\n data-variant=\"voice-card\"\n className={cn(\n \"m-0 rounded-md-lg border border-md-outline-variant bg-md-surface p-5 text-md-on-surface\",\n className,\n )}\n {...props}\n >\n <blockquote className=\"m-0 rounded-md-xs border-l-[3px] border-md-primary bg-md-surface-container px-3.5 py-3 text-sm leading-5 tracking-[0.25px] text-md-on-surface\">\n “{quote}”\n </blockquote>\n {tags.length > 0 && (\n <figcaption className=\"mt-3\">\n <span className=\"sr-only\">Voice: </span>\n <ul className=\"m-0 flex list-none flex-wrap gap-2 p-0\">\n {tags.map((tag) => (\n <li\n key={tag}\n className=\"inline-flex h-6 items-center rounded-md-sm border border-md-outline-variant px-2 text-xs font-medium tracking-[0.5px] text-md-on-surface-variant\"\n >\n {tag}\n </li>\n ))}\n </ul>\n </figcaption>\n )}\n </figure>\n ),\n);\nMd3PersonalityVoiceCard.displayName = \"Md3PersonalityVoiceCard\";\n\n/**\n * The `sample-dialog` in Material 3 — the twin of `PersonalitySampleDialog`.\n * Two authors, two grounds: the person's turns on surface-container-high,\n * the agent's on its primary-container ground, each with the M3 bubble\n * shape (a small corner toward its author). Lines marked `fixed` carry a\n * lock and \"Same in every personality\", so the contract is visible.\n */\nexport const Md3PersonalitySampleDialog = React.forwardRef<HTMLDivElement, Md3PersonalitySampleDialogProps>(\n ({ turns, agentName = \"Assistant\", label = \"Sample dialog\", className, ...props }, ref) => (\n <div\n ref={ref}\n role=\"group\"\n aria-label={label}\n data-variant=\"sample-dialog\"\n className={cn(\"flex flex-col gap-2\", className)}\n {...props}\n >\n {turns.map((turn, i) => {\n const user = turn.from === \"user\";\n return (\n <div\n key={i}\n className={cn(\n \"max-w-[85%] px-3.5 py-2.5 text-xs leading-[18px] tracking-[0.25px]\",\n user\n ? \"self-end rounded-md-lg rounded-br-md-xs bg-md-surface-container-high text-md-on-surface\"\n : \"self-start rounded-md-lg rounded-bl-md-xs bg-md-primary-container text-md-on-primary-container\",\n )}\n >\n <span className=\"sr-only\">{user ? \"You said: \" : `${agentName} said: `}</span>\n {turn.text}\n {turn.fixed && (\n <span className=\"mt-1 flex items-center gap-1 text-[11px] font-medium tracking-[0.5px] opacity-80\">\n <Lock aria-hidden=\"true\" className=\"size-3\" />\n Same in every personality\n </span>\n )}\n </div>\n );\n })}\n </div>\n ),\n);\nMd3PersonalitySampleDialog.displayName = \"Md3PersonalitySampleDialog\";\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.tsx"],"names":["React","defaultTones","jsxs","cn","jsx","Lock","Check"],"mappings":"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","file":"index.cjs","sourcesContent":["import * as React from \"react\";\nimport { Check, Lock } from \"lucide-react\";\nimport { cn } from \"@nucleux/utils\";\nimport { defaultTones } from \"@nucleux/personality\";\nimport type {\n PersonalityProps,\n PersonalityVariant,\n PersonalitySampleDialogProps,\n PersonalityVoiceCardProps,\n} from \"@nucleux/personality\";\n\nexport type { ToneOption, PersonalitySampleTurn } from \"@nucleux/personality\";\nexport { defaultTones } from \"@nucleux/personality\";\nexport type Md3PersonalityProps = PersonalityProps;\nexport type Md3PersonalityVariant = PersonalityVariant;\nexport type Md3PersonalityVoiceCardProps = PersonalityVoiceCardProps;\nexport type Md3PersonalitySampleDialogProps = PersonalitySampleDialogProps;\n\nconst stateLayer =\n \"relative overflow-hidden before:absolute before:inset-0 before:bg-current before:opacity-0 before:transition-opacity before:content-[''] hover:before:opacity-[0.08] focus-visible:before:opacity-[0.12] active:before:opacity-[0.12] motion-reduce:before:transition-none\";\n\n/**\n * The `tone-matrix` in Material 3 — the twin of `Personality`, with the same\n * API and keyboard model. A small set of writing styles as M3 filter chips:\n * the selected one takes the secondary-container role and a leading check;\n * hover, focus and press are the chip's 8% / 12% state layer. It is a radio\n * group with roving focus (arrow keys move and select, Home / End jump).\n * Tone changes how the agent writes, never what it may do — keep\n * permission, caveat and refusal strings outside it. `variant=\"list\"` is\n * the settings-page picker: M3 radio rows with each description visible, a\n * primary-container \"Recommended\" `badge` and a locked `note`.\n */\nexport const Md3Personality = React.forwardRef<HTMLDivElement, Md3PersonalityProps>(\n (\n { options = defaultTones, value, defaultValue, onValueChange, label = \"Tone\", variant = \"chips\", note, className, ...props },\n ref,\n ) => {\n const list = variant === \"list\";\n // Selection and roving-focus logic copied from @nucleux/personality (internal there).\n const [internal, setInternal] = React.useState<string | undefined>(defaultValue);\n const current = value !== undefined ? value : internal;\n const refs = React.useRef<(HTMLButtonElement | null)[]>([]);\n const descId = React.useId();\n const select = (next: string) => {\n if (value === undefined) setInternal(next);\n onValueChange?.(next);\n };\n const selectedIndex = options.findIndex((o) => o.value === current);\n const tabStop = selectedIndex >= 0 ? selectedIndex : 0;\n\n const onKeyDown = (e: React.KeyboardEvent, index: number) => {\n const last = options.length - 1;\n let next: number | null = null;\n if (e.key === \"ArrowRight\" || e.key === \"ArrowDown\") next = index === last ? 0 : index + 1;\n else if (e.key === \"ArrowLeft\" || e.key === \"ArrowUp\") next = index === 0 ? last : index - 1;\n else if (e.key === \"Home\") next = 0;\n else if (e.key === \"End\") next = last;\n if (next === null) return;\n e.preventDefault();\n refs.current[next]?.focus();\n select(options[next]!.value);\n };\n\n return (\n <div\n ref={ref}\n data-variant=\"tone-matrix\"\n data-layout={variant}\n className={cn(\"flex flex-col gap-2\", className)}\n {...props}\n >\n {label && (\n <span\n className={\n list\n ? \"text-lg font-semibold text-md-on-surface\"\n : \"text-xs font-medium tracking-[0.5px] text-md-on-surface-variant\"\n }\n >\n {label}\n </span>\n )}\n {note && (\n <p className=\"m-0 mt-2 flex items-center gap-1.5 text-sm tracking-[0.25px] text-md-on-surface-variant\">\n <Lock aria-hidden=\"true\" className=\"size-4 shrink-0\" />\n {note}\n </p>\n )}\n <div\n role=\"radiogroup\"\n aria-label={typeof label === \"string\" ? label : \"Tone\"}\n className={list ? \"mt-2 flex flex-col\" : \"flex flex-wrap gap-2\"}\n >\n {options.map((option, index) => {\n const active = current === option.value;\n if (list) {\n return (\n <button\n key={option.value}\n ref={(el) => {\n refs.current[index] = el;\n }}\n type=\"button\"\n role=\"radio\"\n aria-checked={active}\n aria-describedby={option.description ? `${descId}-${index}` : undefined}\n tabIndex={index === tabStop ? 0 : -1}\n onClick={() => select(option.value)}\n onKeyDown={(e) => onKeyDown(e, index)}\n className={cn(\n \"flex items-start gap-4 rounded-md-md py-2 pl-2.5 pr-3 text-left outline-none focus-visible:ring-2 focus-visible:ring-md-primary\",\n stateLayer,\n )}\n >\n <span\n aria-hidden=\"true\"\n className={cn(\n \"relative mt-0.5 grid size-5 shrink-0 place-items-center rounded-full border-2 transition-colors motion-reduce:transition-none\",\n active ? \"border-md-primary\" : \"border-md-on-surface-variant\",\n )}\n >\n {active && <span className=\"size-2.5 rounded-full bg-md-primary\" />}\n </span>\n <span className=\"relative flex flex-col gap-1\">\n <span className=\"flex items-center gap-2 text-base text-md-on-surface\">\n {option.icon}\n {option.label}\n {option.badge != null && (\n <span className=\"rounded-md-sm bg-md-primary-container px-1.5 py-0.5 text-xs font-semibold tracking-[0.5px] text-md-on-primary-container\">\n {option.badge}\n </span>\n )}\n </span>\n {option.description && (\n <span id={`${descId}-${index}`} className=\"text-sm tracking-[0.25px] text-md-on-surface-variant\">\n {option.description}\n </span>\n )}\n </span>\n </button>\n );\n }\n return (\n <button\n key={option.value}\n ref={(el) => {\n refs.current[index] = el;\n }}\n type=\"button\"\n role=\"radio\"\n aria-checked={active}\n aria-describedby={option.description ? `${descId}-${index}` : undefined}\n tabIndex={index === tabStop ? 0 : -1}\n onClick={() => select(option.value)}\n onKeyDown={(e) => onKeyDown(e, index)}\n className={cn(\n \"inline-flex h-8 items-center gap-2 rounded-md-sm border px-3 text-sm font-medium tracking-[0.1px] outline-none transition-colors focus-visible:ring-2 focus-visible:ring-md-primary motion-reduce:transition-none [&_svg]:relative [&_svg]:size-[18px]\",\n stateLayer,\n active\n ? \"border-transparent bg-md-secondary-container pl-2 text-md-on-secondary-container\"\n : \"border-md-outline bg-transparent text-md-on-surface-variant\",\n )}\n >\n {active && option.icon == null && <Check aria-hidden=\"true\" />}\n {option.icon}\n <span className=\"relative\">{option.label}</span>\n {option.description && (\n <span id={`${descId}-${index}`} className=\"sr-only\">\n {option.description}\n </span>\n )}\n </button>\n );\n })}\n </div>\n </div>\n );\n },\n);\nMd3Personality.displayName = \"Md3Personality\";\n\n/**\n * The `voice-card` in Material 3 — the twin of `PersonalityVoiceCard`. An\n * outlined card whose sample utterance sits on a surface-container ground\n * behind a primary rule (the voice, written down), with the voice tags as\n * outlined chips beneath it.\n */\nexport const Md3PersonalityVoiceCard = React.forwardRef<HTMLElement, Md3PersonalityVoiceCardProps>(\n ({ quote, tags = [], label = \"Voice\", className, ...props }, ref) => (\n <figure\n ref={ref}\n aria-label={label}\n data-variant=\"voice-card\"\n className={cn(\n \"m-0 rounded-md-lg border border-md-outline-variant bg-md-surface p-5 text-md-on-surface\",\n className,\n )}\n {...props}\n >\n <blockquote className=\"m-0 rounded-md-xs border-l-[3px] border-md-primary bg-md-surface-container px-3.5 py-3 text-sm leading-5 tracking-[0.25px] text-md-on-surface\">\n “{quote}”\n </blockquote>\n {tags.length > 0 && (\n <figcaption className=\"mt-3\">\n <span className=\"sr-only\">Voice: </span>\n <ul className=\"m-0 flex list-none flex-wrap gap-2 p-0\">\n {tags.map((tag) => (\n <li\n key={tag}\n className=\"inline-flex h-6 items-center rounded-md-sm border border-md-outline-variant px-2 text-xs font-medium tracking-[0.5px] text-md-on-surface-variant\"\n >\n {tag}\n </li>\n ))}\n </ul>\n </figcaption>\n )}\n </figure>\n ),\n);\nMd3PersonalityVoiceCard.displayName = \"Md3PersonalityVoiceCard\";\n\n/**\n * The `sample-dialog` in Material 3 — the twin of `PersonalitySampleDialog`.\n * Two authors, two grounds: the person's turns on surface-container-high,\n * the agent's on its primary-container ground, each with the M3 bubble\n * shape (a small corner toward its author). Lines marked `fixed` carry a\n * lock and \"Same in every personality\", so the contract is visible.\n */\nexport const Md3PersonalitySampleDialog = React.forwardRef<HTMLDivElement, Md3PersonalitySampleDialogProps>(\n ({ turns, agentName = \"Assistant\", label = \"Sample dialog\", className, ...props }, ref) => (\n <div\n ref={ref}\n role=\"group\"\n aria-label={label}\n data-variant=\"sample-dialog\"\n className={cn(\"flex flex-col gap-2\", className)}\n {...props}\n >\n {turns.map((turn, i) => {\n const user = turn.from === \"user\";\n return (\n <div\n key={i}\n className={cn(\n \"max-w-[85%] px-3.5 py-2.5 text-xs leading-[18px] tracking-[0.25px]\",\n user\n ? \"self-end rounded-md-lg rounded-br-md-xs bg-md-surface-container-high text-md-on-surface\"\n : \"self-start rounded-md-lg rounded-bl-md-xs bg-md-primary-container text-md-on-primary-container\",\n )}\n >\n <span className=\"sr-only\">{user ? \"You said: \" : `${agentName} said: `}</span>\n {turn.text}\n {turn.fixed && (\n <span className=\"mt-1 flex items-center gap-1 text-[11px] font-medium tracking-[0.5px] opacity-80\">\n <Lock aria-hidden=\"true\" className=\"size-3\" />\n Same in every personality\n </span>\n )}\n </div>\n );\n })}\n </div>\n ),\n);\nMd3PersonalitySampleDialog.displayName = \"Md3PersonalitySampleDialog\";\n"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import { PersonalityProps, PersonalitySampleDialogProps, PersonalityVoiceCardProps } from '@nucleux/personality';
|
|
2
|
+
import { PersonalityProps, PersonalitySampleDialogProps, PersonalityVariant, PersonalityVoiceCardProps } from '@nucleux/personality';
|
|
3
3
|
export { PersonalitySampleTurn, ToneOption, defaultTones } from '@nucleux/personality';
|
|
4
4
|
|
|
5
5
|
type Md3PersonalityProps = PersonalityProps;
|
|
6
|
+
type Md3PersonalityVariant = PersonalityVariant;
|
|
6
7
|
type Md3PersonalityVoiceCardProps = PersonalityVoiceCardProps;
|
|
7
8
|
type Md3PersonalitySampleDialogProps = PersonalitySampleDialogProps;
|
|
8
9
|
/**
|
|
@@ -12,7 +13,9 @@ type Md3PersonalitySampleDialogProps = PersonalitySampleDialogProps;
|
|
|
12
13
|
* hover, focus and press are the chip's 8% / 12% state layer. It is a radio
|
|
13
14
|
* group with roving focus (arrow keys move and select, Home / End jump).
|
|
14
15
|
* Tone changes how the agent writes, never what it may do — keep
|
|
15
|
-
* permission, caveat and refusal strings outside it.
|
|
16
|
+
* permission, caveat and refusal strings outside it. `variant="list"` is
|
|
17
|
+
* the settings-page picker: M3 radio rows with each description visible, a
|
|
18
|
+
* primary-container "Recommended" `badge` and a locked `note`.
|
|
16
19
|
*/
|
|
17
20
|
declare const Md3Personality: React.ForwardRefExoticComponent<PersonalityProps & React.RefAttributes<HTMLDivElement>>;
|
|
18
21
|
/**
|
|
@@ -31,4 +34,4 @@ declare const Md3PersonalityVoiceCard: React.ForwardRefExoticComponent<Personali
|
|
|
31
34
|
*/
|
|
32
35
|
declare const Md3PersonalitySampleDialog: React.ForwardRefExoticComponent<PersonalitySampleDialogProps & React.RefAttributes<HTMLDivElement>>;
|
|
33
36
|
|
|
34
|
-
export { Md3Personality, type Md3PersonalityProps, Md3PersonalitySampleDialog, type Md3PersonalitySampleDialogProps, Md3PersonalityVoiceCard, type Md3PersonalityVoiceCardProps };
|
|
37
|
+
export { Md3Personality, type Md3PersonalityProps, Md3PersonalitySampleDialog, type Md3PersonalitySampleDialogProps, type Md3PersonalityVariant, Md3PersonalityVoiceCard, type Md3PersonalityVoiceCardProps };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import { PersonalityProps, PersonalitySampleDialogProps, PersonalityVoiceCardProps } from '@nucleux/personality';
|
|
2
|
+
import { PersonalityProps, PersonalitySampleDialogProps, PersonalityVariant, PersonalityVoiceCardProps } from '@nucleux/personality';
|
|
3
3
|
export { PersonalitySampleTurn, ToneOption, defaultTones } from '@nucleux/personality';
|
|
4
4
|
|
|
5
5
|
type Md3PersonalityProps = PersonalityProps;
|
|
6
|
+
type Md3PersonalityVariant = PersonalityVariant;
|
|
6
7
|
type Md3PersonalityVoiceCardProps = PersonalityVoiceCardProps;
|
|
7
8
|
type Md3PersonalitySampleDialogProps = PersonalitySampleDialogProps;
|
|
8
9
|
/**
|
|
@@ -12,7 +13,9 @@ type Md3PersonalitySampleDialogProps = PersonalitySampleDialogProps;
|
|
|
12
13
|
* hover, focus and press are the chip's 8% / 12% state layer. It is a radio
|
|
13
14
|
* group with roving focus (arrow keys move and select, Home / End jump).
|
|
14
15
|
* Tone changes how the agent writes, never what it may do — keep
|
|
15
|
-
* permission, caveat and refusal strings outside it.
|
|
16
|
+
* permission, caveat and refusal strings outside it. `variant="list"` is
|
|
17
|
+
* the settings-page picker: M3 radio rows with each description visible, a
|
|
18
|
+
* primary-container "Recommended" `badge` and a locked `note`.
|
|
16
19
|
*/
|
|
17
20
|
declare const Md3Personality: React.ForwardRefExoticComponent<PersonalityProps & React.RefAttributes<HTMLDivElement>>;
|
|
18
21
|
/**
|
|
@@ -31,4 +34,4 @@ declare const Md3PersonalityVoiceCard: React.ForwardRefExoticComponent<Personali
|
|
|
31
34
|
*/
|
|
32
35
|
declare const Md3PersonalitySampleDialog: React.ForwardRefExoticComponent<PersonalitySampleDialogProps & React.RefAttributes<HTMLDivElement>>;
|
|
33
36
|
|
|
34
|
-
export { Md3Personality, type Md3PersonalityProps, Md3PersonalitySampleDialog, type Md3PersonalitySampleDialogProps, Md3PersonalityVoiceCard, type Md3PersonalityVoiceCardProps };
|
|
37
|
+
export { Md3Personality, type Md3PersonalityProps, Md3PersonalitySampleDialog, type Md3PersonalitySampleDialogProps, type Md3PersonalityVariant, Md3PersonalityVoiceCard, type Md3PersonalityVoiceCardProps };
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import * as React from 'react';
|
|
3
|
-
import {
|
|
3
|
+
import { Lock, Check } from 'lucide-react';
|
|
4
4
|
import { cn } from '@nucleux/utils';
|
|
5
5
|
import { defaultTones } from '@nucleux/personality';
|
|
6
6
|
export { defaultTones } from '@nucleux/personality';
|
|
@@ -9,7 +9,8 @@ import { jsxs, jsx } from 'react/jsx-runtime';
|
|
|
9
9
|
// src/index.tsx
|
|
10
10
|
var stateLayer = "relative overflow-hidden before:absolute before:inset-0 before:bg-current before:opacity-0 before:transition-opacity before:content-[''] hover:before:opacity-[0.08] focus-visible:before:opacity-[0.12] active:before:opacity-[0.12] motion-reduce:before:transition-none";
|
|
11
11
|
var Md3Personality = React.forwardRef(
|
|
12
|
-
({ options = defaultTones, value, defaultValue, onValueChange, label = "Tone", className, ...props }, ref) => {
|
|
12
|
+
({ options = defaultTones, value, defaultValue, onValueChange, label = "Tone", variant = "chips", note, className, ...props }, ref) => {
|
|
13
|
+
const list = variant === "list";
|
|
13
14
|
const [internal, setInternal] = React.useState(defaultValue);
|
|
14
15
|
const current = value !== void 0 ? value : internal;
|
|
15
16
|
const refs = React.useRef([]);
|
|
@@ -32,47 +33,110 @@ var Md3Personality = React.forwardRef(
|
|
|
32
33
|
refs.current[next]?.focus();
|
|
33
34
|
select(options[next].value);
|
|
34
35
|
};
|
|
35
|
-
return /* @__PURE__ */ jsxs(
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
36
|
+
return /* @__PURE__ */ jsxs(
|
|
37
|
+
"div",
|
|
38
|
+
{
|
|
39
|
+
ref,
|
|
40
|
+
"data-variant": "tone-matrix",
|
|
41
|
+
"data-layout": variant,
|
|
42
|
+
className: cn("flex flex-col gap-2", className),
|
|
43
|
+
...props,
|
|
44
|
+
children: [
|
|
45
|
+
label && /* @__PURE__ */ jsx(
|
|
46
|
+
"span",
|
|
47
|
+
{
|
|
48
|
+
className: list ? "text-lg font-semibold text-md-on-surface" : "text-xs font-medium tracking-[0.5px] text-md-on-surface-variant",
|
|
49
|
+
children: label
|
|
50
|
+
}
|
|
51
|
+
),
|
|
52
|
+
note && /* @__PURE__ */ jsxs("p", { className: "m-0 mt-2 flex items-center gap-1.5 text-sm tracking-[0.25px] text-md-on-surface-variant", children: [
|
|
53
|
+
/* @__PURE__ */ jsx(Lock, { "aria-hidden": "true", className: "size-4 shrink-0" }),
|
|
54
|
+
note
|
|
55
|
+
] }),
|
|
56
|
+
/* @__PURE__ */ jsx(
|
|
57
|
+
"div",
|
|
58
|
+
{
|
|
59
|
+
role: "radiogroup",
|
|
60
|
+
"aria-label": typeof label === "string" ? label : "Tone",
|
|
61
|
+
className: list ? "mt-2 flex flex-col" : "flex flex-wrap gap-2",
|
|
62
|
+
children: options.map((option, index) => {
|
|
63
|
+
const active = current === option.value;
|
|
64
|
+
if (list) {
|
|
65
|
+
return /* @__PURE__ */ jsxs(
|
|
66
|
+
"button",
|
|
67
|
+
{
|
|
68
|
+
ref: (el) => {
|
|
69
|
+
refs.current[index] = el;
|
|
70
|
+
},
|
|
71
|
+
type: "button",
|
|
72
|
+
role: "radio",
|
|
73
|
+
"aria-checked": active,
|
|
74
|
+
"aria-describedby": option.description ? `${descId}-${index}` : void 0,
|
|
75
|
+
tabIndex: index === tabStop ? 0 : -1,
|
|
76
|
+
onClick: () => select(option.value),
|
|
77
|
+
onKeyDown: (e) => onKeyDown(e, index),
|
|
78
|
+
className: cn(
|
|
79
|
+
"flex items-start gap-4 rounded-md-md py-2 pl-2.5 pr-3 text-left outline-none focus-visible:ring-2 focus-visible:ring-md-primary",
|
|
80
|
+
stateLayer
|
|
81
|
+
),
|
|
82
|
+
children: [
|
|
83
|
+
/* @__PURE__ */ jsx(
|
|
84
|
+
"span",
|
|
85
|
+
{
|
|
86
|
+
"aria-hidden": "true",
|
|
87
|
+
className: cn(
|
|
88
|
+
"relative mt-0.5 grid size-5 shrink-0 place-items-center rounded-full border-2 transition-colors motion-reduce:transition-none",
|
|
89
|
+
active ? "border-md-primary" : "border-md-on-surface-variant"
|
|
90
|
+
),
|
|
91
|
+
children: active && /* @__PURE__ */ jsx("span", { className: "size-2.5 rounded-full bg-md-primary" })
|
|
92
|
+
}
|
|
93
|
+
),
|
|
94
|
+
/* @__PURE__ */ jsxs("span", { className: "relative flex flex-col gap-1", children: [
|
|
95
|
+
/* @__PURE__ */ jsxs("span", { className: "flex items-center gap-2 text-base text-md-on-surface", children: [
|
|
96
|
+
option.icon,
|
|
97
|
+
option.label,
|
|
98
|
+
option.badge != null && /* @__PURE__ */ jsx("span", { className: "rounded-md-sm bg-md-primary-container px-1.5 py-0.5 text-xs font-semibold tracking-[0.5px] text-md-on-primary-container", children: option.badge })
|
|
99
|
+
] }),
|
|
100
|
+
option.description && /* @__PURE__ */ jsx("span", { id: `${descId}-${index}`, className: "text-sm tracking-[0.25px] text-md-on-surface-variant", children: option.description })
|
|
101
|
+
] })
|
|
102
|
+
]
|
|
103
|
+
},
|
|
104
|
+
option.value
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
return /* @__PURE__ */ jsxs(
|
|
108
|
+
"button",
|
|
109
|
+
{
|
|
110
|
+
ref: (el) => {
|
|
111
|
+
refs.current[index] = el;
|
|
112
|
+
},
|
|
113
|
+
type: "button",
|
|
114
|
+
role: "radio",
|
|
115
|
+
"aria-checked": active,
|
|
116
|
+
"aria-describedby": option.description ? `${descId}-${index}` : void 0,
|
|
117
|
+
tabIndex: index === tabStop ? 0 : -1,
|
|
118
|
+
onClick: () => select(option.value),
|
|
119
|
+
onKeyDown: (e) => onKeyDown(e, index),
|
|
120
|
+
className: cn(
|
|
121
|
+
"inline-flex h-8 items-center gap-2 rounded-md-sm border px-3 text-sm font-medium tracking-[0.1px] outline-none transition-colors focus-visible:ring-2 focus-visible:ring-md-primary motion-reduce:transition-none [&_svg]:relative [&_svg]:size-[18px]",
|
|
122
|
+
stateLayer,
|
|
123
|
+
active ? "border-transparent bg-md-secondary-container pl-2 text-md-on-secondary-container" : "border-md-outline bg-transparent text-md-on-surface-variant"
|
|
124
|
+
),
|
|
125
|
+
children: [
|
|
126
|
+
active && option.icon == null && /* @__PURE__ */ jsx(Check, { "aria-hidden": "true" }),
|
|
127
|
+
option.icon,
|
|
128
|
+
/* @__PURE__ */ jsx("span", { className: "relative", children: option.label }),
|
|
129
|
+
option.description && /* @__PURE__ */ jsx("span", { id: `${descId}-${index}`, className: "sr-only", children: option.description })
|
|
130
|
+
]
|
|
131
|
+
},
|
|
132
|
+
option.value
|
|
133
|
+
);
|
|
134
|
+
})
|
|
135
|
+
}
|
|
136
|
+
)
|
|
137
|
+
]
|
|
138
|
+
}
|
|
139
|
+
);
|
|
76
140
|
}
|
|
77
141
|
);
|
|
78
142
|
Md3Personality.displayName = "Md3Personality";
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.tsx"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import * as React from \"react\";\nimport { Check, Lock } from \"lucide-react\";\nimport { cn } from \"@nucleux/utils\";\nimport { defaultTones } from \"@nucleux/personality\";\nimport type {\n PersonalityProps,\n PersonalitySampleDialogProps,\n PersonalityVoiceCardProps,\n} from \"@nucleux/personality\";\n\nexport type { ToneOption, PersonalitySampleTurn } from \"@nucleux/personality\";\nexport { defaultTones } from \"@nucleux/personality\";\nexport type Md3PersonalityProps = PersonalityProps;\nexport type Md3PersonalityVoiceCardProps = PersonalityVoiceCardProps;\nexport type Md3PersonalitySampleDialogProps = PersonalitySampleDialogProps;\n\nconst stateLayer =\n \"relative overflow-hidden before:absolute before:inset-0 before:bg-current before:opacity-0 before:transition-opacity before:content-[''] hover:before:opacity-[0.08] focus-visible:before:opacity-[0.12] active:before:opacity-[0.12] motion-reduce:before:transition-none\";\n\n/**\n * The `tone-matrix` in Material 3 — the twin of `Personality`, with the same\n * API and keyboard model. A small set of writing styles as M3 filter chips:\n * the selected one takes the secondary-container role and a leading check;\n * hover, focus and press are the chip's 8% / 12% state layer. It is a radio\n * group with roving focus (arrow keys move and select, Home / End jump).\n * Tone changes how the agent writes, never what it may do — keep\n * permission, caveat and refusal strings outside it.\n */\nexport const Md3Personality = React.forwardRef<HTMLDivElement, Md3PersonalityProps>(\n ({ options = defaultTones, value, defaultValue, onValueChange, label = \"Tone\", className, ...props }, ref) => {\n // Selection and roving-focus logic copied from @nucleux/personality (internal there).\n const [internal, setInternal] = React.useState<string | undefined>(defaultValue);\n const current = value !== undefined ? value : internal;\n const refs = React.useRef<(HTMLButtonElement | null)[]>([]);\n const descId = React.useId();\n const select = (next: string) => {\n if (value === undefined) setInternal(next);\n onValueChange?.(next);\n };\n const selectedIndex = options.findIndex((o) => o.value === current);\n const tabStop = selectedIndex >= 0 ? selectedIndex : 0;\n\n const onKeyDown = (e: React.KeyboardEvent, index: number) => {\n const last = options.length - 1;\n let next: number | null = null;\n if (e.key === \"ArrowRight\" || e.key === \"ArrowDown\") next = index === last ? 0 : index + 1;\n else if (e.key === \"ArrowLeft\" || e.key === \"ArrowUp\") next = index === 0 ? last : index - 1;\n else if (e.key === \"Home\") next = 0;\n else if (e.key === \"End\") next = last;\n if (next === null) return;\n e.preventDefault();\n refs.current[next]?.focus();\n select(options[next]!.value);\n };\n\n return (\n <div ref={ref} data-variant=\"tone-matrix\" className={cn(\"flex flex-col gap-2\", className)} {...props}>\n {label && (\n <span className=\"text-xs font-medium tracking-[0.5px] text-md-on-surface-variant\">{label}</span>\n )}\n <div\n role=\"radiogroup\"\n aria-label={typeof label === \"string\" ? label : \"Tone\"}\n className=\"flex flex-wrap gap-2\"\n >\n {options.map((option, index) => {\n const active = current === option.value;\n return (\n <button\n key={option.value}\n ref={(el) => {\n refs.current[index] = el;\n }}\n type=\"button\"\n role=\"radio\"\n aria-checked={active}\n aria-describedby={option.description ? `${descId}-${index}` : undefined}\n tabIndex={index === tabStop ? 0 : -1}\n onClick={() => select(option.value)}\n onKeyDown={(e) => onKeyDown(e, index)}\n className={cn(\n \"inline-flex h-8 items-center gap-2 rounded-md-sm border px-3 text-sm font-medium tracking-[0.1px] outline-none transition-colors focus-visible:ring-2 focus-visible:ring-md-primary motion-reduce:transition-none [&_svg]:relative [&_svg]:size-[18px]\",\n stateLayer,\n active\n ? \"border-transparent bg-md-secondary-container pl-2 text-md-on-secondary-container\"\n : \"border-md-outline bg-transparent text-md-on-surface-variant\",\n )}\n >\n {active && option.icon == null && <Check aria-hidden=\"true\" />}\n {option.icon}\n <span className=\"relative\">{option.label}</span>\n {option.description && (\n <span id={`${descId}-${index}`} className=\"sr-only\">\n {option.description}\n </span>\n )}\n </button>\n );\n })}\n </div>\n </div>\n );\n },\n);\nMd3Personality.displayName = \"Md3Personality\";\n\n/**\n * The `voice-card` in Material 3 — the twin of `PersonalityVoiceCard`. An\n * outlined card whose sample utterance sits on a surface-container ground\n * behind a primary rule (the voice, written down), with the voice tags as\n * outlined chips beneath it.\n */\nexport const Md3PersonalityVoiceCard = React.forwardRef<HTMLElement, Md3PersonalityVoiceCardProps>(\n ({ quote, tags = [], label = \"Voice\", className, ...props }, ref) => (\n <figure\n ref={ref}\n aria-label={label}\n data-variant=\"voice-card\"\n className={cn(\n \"m-0 rounded-md-lg border border-md-outline-variant bg-md-surface p-5 text-md-on-surface\",\n className,\n )}\n {...props}\n >\n <blockquote className=\"m-0 rounded-md-xs border-l-[3px] border-md-primary bg-md-surface-container px-3.5 py-3 text-sm leading-5 tracking-[0.25px] text-md-on-surface\">\n “{quote}”\n </blockquote>\n {tags.length > 0 && (\n <figcaption className=\"mt-3\">\n <span className=\"sr-only\">Voice: </span>\n <ul className=\"m-0 flex list-none flex-wrap gap-2 p-0\">\n {tags.map((tag) => (\n <li\n key={tag}\n className=\"inline-flex h-6 items-center rounded-md-sm border border-md-outline-variant px-2 text-xs font-medium tracking-[0.5px] text-md-on-surface-variant\"\n >\n {tag}\n </li>\n ))}\n </ul>\n </figcaption>\n )}\n </figure>\n ),\n);\nMd3PersonalityVoiceCard.displayName = \"Md3PersonalityVoiceCard\";\n\n/**\n * The `sample-dialog` in Material 3 — the twin of `PersonalitySampleDialog`.\n * Two authors, two grounds: the person's turns on surface-container-high,\n * the agent's on its primary-container ground, each with the M3 bubble\n * shape (a small corner toward its author). Lines marked `fixed` carry a\n * lock and \"Same in every personality\", so the contract is visible.\n */\nexport const Md3PersonalitySampleDialog = React.forwardRef<HTMLDivElement, Md3PersonalitySampleDialogProps>(\n ({ turns, agentName = \"Assistant\", label = \"Sample dialog\", className, ...props }, ref) => (\n <div\n ref={ref}\n role=\"group\"\n aria-label={label}\n data-variant=\"sample-dialog\"\n className={cn(\"flex flex-col gap-2\", className)}\n {...props}\n >\n {turns.map((turn, i) => {\n const user = turn.from === \"user\";\n return (\n <div\n key={i}\n className={cn(\n \"max-w-[85%] px-3.5 py-2.5 text-xs leading-[18px] tracking-[0.25px]\",\n user\n ? \"self-end rounded-md-lg rounded-br-md-xs bg-md-surface-container-high text-md-on-surface\"\n : \"self-start rounded-md-lg rounded-bl-md-xs bg-md-primary-container text-md-on-primary-container\",\n )}\n >\n <span className=\"sr-only\">{user ? \"You said: \" : `${agentName} said: `}</span>\n {turn.text}\n {turn.fixed && (\n <span className=\"mt-1 flex items-center gap-1 text-[11px] font-medium tracking-[0.5px] opacity-80\">\n <Lock aria-hidden=\"true\" className=\"size-3\" />\n Same in every personality\n </span>\n )}\n </div>\n );\n })}\n </div>\n ),\n);\nMd3PersonalitySampleDialog.displayName = \"Md3PersonalitySampleDialog\";\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.tsx"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import * as React from \"react\";\nimport { Check, Lock } from \"lucide-react\";\nimport { cn } from \"@nucleux/utils\";\nimport { defaultTones } from \"@nucleux/personality\";\nimport type {\n PersonalityProps,\n PersonalityVariant,\n PersonalitySampleDialogProps,\n PersonalityVoiceCardProps,\n} from \"@nucleux/personality\";\n\nexport type { ToneOption, PersonalitySampleTurn } from \"@nucleux/personality\";\nexport { defaultTones } from \"@nucleux/personality\";\nexport type Md3PersonalityProps = PersonalityProps;\nexport type Md3PersonalityVariant = PersonalityVariant;\nexport type Md3PersonalityVoiceCardProps = PersonalityVoiceCardProps;\nexport type Md3PersonalitySampleDialogProps = PersonalitySampleDialogProps;\n\nconst stateLayer =\n \"relative overflow-hidden before:absolute before:inset-0 before:bg-current before:opacity-0 before:transition-opacity before:content-[''] hover:before:opacity-[0.08] focus-visible:before:opacity-[0.12] active:before:opacity-[0.12] motion-reduce:before:transition-none\";\n\n/**\n * The `tone-matrix` in Material 3 — the twin of `Personality`, with the same\n * API and keyboard model. A small set of writing styles as M3 filter chips:\n * the selected one takes the secondary-container role and a leading check;\n * hover, focus and press are the chip's 8% / 12% state layer. It is a radio\n * group with roving focus (arrow keys move and select, Home / End jump).\n * Tone changes how the agent writes, never what it may do — keep\n * permission, caveat and refusal strings outside it. `variant=\"list\"` is\n * the settings-page picker: M3 radio rows with each description visible, a\n * primary-container \"Recommended\" `badge` and a locked `note`.\n */\nexport const Md3Personality = React.forwardRef<HTMLDivElement, Md3PersonalityProps>(\n (\n { options = defaultTones, value, defaultValue, onValueChange, label = \"Tone\", variant = \"chips\", note, className, ...props },\n ref,\n ) => {\n const list = variant === \"list\";\n // Selection and roving-focus logic copied from @nucleux/personality (internal there).\n const [internal, setInternal] = React.useState<string | undefined>(defaultValue);\n const current = value !== undefined ? value : internal;\n const refs = React.useRef<(HTMLButtonElement | null)[]>([]);\n const descId = React.useId();\n const select = (next: string) => {\n if (value === undefined) setInternal(next);\n onValueChange?.(next);\n };\n const selectedIndex = options.findIndex((o) => o.value === current);\n const tabStop = selectedIndex >= 0 ? selectedIndex : 0;\n\n const onKeyDown = (e: React.KeyboardEvent, index: number) => {\n const last = options.length - 1;\n let next: number | null = null;\n if (e.key === \"ArrowRight\" || e.key === \"ArrowDown\") next = index === last ? 0 : index + 1;\n else if (e.key === \"ArrowLeft\" || e.key === \"ArrowUp\") next = index === 0 ? last : index - 1;\n else if (e.key === \"Home\") next = 0;\n else if (e.key === \"End\") next = last;\n if (next === null) return;\n e.preventDefault();\n refs.current[next]?.focus();\n select(options[next]!.value);\n };\n\n return (\n <div\n ref={ref}\n data-variant=\"tone-matrix\"\n data-layout={variant}\n className={cn(\"flex flex-col gap-2\", className)}\n {...props}\n >\n {label && (\n <span\n className={\n list\n ? \"text-lg font-semibold text-md-on-surface\"\n : \"text-xs font-medium tracking-[0.5px] text-md-on-surface-variant\"\n }\n >\n {label}\n </span>\n )}\n {note && (\n <p className=\"m-0 mt-2 flex items-center gap-1.5 text-sm tracking-[0.25px] text-md-on-surface-variant\">\n <Lock aria-hidden=\"true\" className=\"size-4 shrink-0\" />\n {note}\n </p>\n )}\n <div\n role=\"radiogroup\"\n aria-label={typeof label === \"string\" ? label : \"Tone\"}\n className={list ? \"mt-2 flex flex-col\" : \"flex flex-wrap gap-2\"}\n >\n {options.map((option, index) => {\n const active = current === option.value;\n if (list) {\n return (\n <button\n key={option.value}\n ref={(el) => {\n refs.current[index] = el;\n }}\n type=\"button\"\n role=\"radio\"\n aria-checked={active}\n aria-describedby={option.description ? `${descId}-${index}` : undefined}\n tabIndex={index === tabStop ? 0 : -1}\n onClick={() => select(option.value)}\n onKeyDown={(e) => onKeyDown(e, index)}\n className={cn(\n \"flex items-start gap-4 rounded-md-md py-2 pl-2.5 pr-3 text-left outline-none focus-visible:ring-2 focus-visible:ring-md-primary\",\n stateLayer,\n )}\n >\n <span\n aria-hidden=\"true\"\n className={cn(\n \"relative mt-0.5 grid size-5 shrink-0 place-items-center rounded-full border-2 transition-colors motion-reduce:transition-none\",\n active ? \"border-md-primary\" : \"border-md-on-surface-variant\",\n )}\n >\n {active && <span className=\"size-2.5 rounded-full bg-md-primary\" />}\n </span>\n <span className=\"relative flex flex-col gap-1\">\n <span className=\"flex items-center gap-2 text-base text-md-on-surface\">\n {option.icon}\n {option.label}\n {option.badge != null && (\n <span className=\"rounded-md-sm bg-md-primary-container px-1.5 py-0.5 text-xs font-semibold tracking-[0.5px] text-md-on-primary-container\">\n {option.badge}\n </span>\n )}\n </span>\n {option.description && (\n <span id={`${descId}-${index}`} className=\"text-sm tracking-[0.25px] text-md-on-surface-variant\">\n {option.description}\n </span>\n )}\n </span>\n </button>\n );\n }\n return (\n <button\n key={option.value}\n ref={(el) => {\n refs.current[index] = el;\n }}\n type=\"button\"\n role=\"radio\"\n aria-checked={active}\n aria-describedby={option.description ? `${descId}-${index}` : undefined}\n tabIndex={index === tabStop ? 0 : -1}\n onClick={() => select(option.value)}\n onKeyDown={(e) => onKeyDown(e, index)}\n className={cn(\n \"inline-flex h-8 items-center gap-2 rounded-md-sm border px-3 text-sm font-medium tracking-[0.1px] outline-none transition-colors focus-visible:ring-2 focus-visible:ring-md-primary motion-reduce:transition-none [&_svg]:relative [&_svg]:size-[18px]\",\n stateLayer,\n active\n ? \"border-transparent bg-md-secondary-container pl-2 text-md-on-secondary-container\"\n : \"border-md-outline bg-transparent text-md-on-surface-variant\",\n )}\n >\n {active && option.icon == null && <Check aria-hidden=\"true\" />}\n {option.icon}\n <span className=\"relative\">{option.label}</span>\n {option.description && (\n <span id={`${descId}-${index}`} className=\"sr-only\">\n {option.description}\n </span>\n )}\n </button>\n );\n })}\n </div>\n </div>\n );\n },\n);\nMd3Personality.displayName = \"Md3Personality\";\n\n/**\n * The `voice-card` in Material 3 — the twin of `PersonalityVoiceCard`. An\n * outlined card whose sample utterance sits on a surface-container ground\n * behind a primary rule (the voice, written down), with the voice tags as\n * outlined chips beneath it.\n */\nexport const Md3PersonalityVoiceCard = React.forwardRef<HTMLElement, Md3PersonalityVoiceCardProps>(\n ({ quote, tags = [], label = \"Voice\", className, ...props }, ref) => (\n <figure\n ref={ref}\n aria-label={label}\n data-variant=\"voice-card\"\n className={cn(\n \"m-0 rounded-md-lg border border-md-outline-variant bg-md-surface p-5 text-md-on-surface\",\n className,\n )}\n {...props}\n >\n <blockquote className=\"m-0 rounded-md-xs border-l-[3px] border-md-primary bg-md-surface-container px-3.5 py-3 text-sm leading-5 tracking-[0.25px] text-md-on-surface\">\n “{quote}”\n </blockquote>\n {tags.length > 0 && (\n <figcaption className=\"mt-3\">\n <span className=\"sr-only\">Voice: </span>\n <ul className=\"m-0 flex list-none flex-wrap gap-2 p-0\">\n {tags.map((tag) => (\n <li\n key={tag}\n className=\"inline-flex h-6 items-center rounded-md-sm border border-md-outline-variant px-2 text-xs font-medium tracking-[0.5px] text-md-on-surface-variant\"\n >\n {tag}\n </li>\n ))}\n </ul>\n </figcaption>\n )}\n </figure>\n ),\n);\nMd3PersonalityVoiceCard.displayName = \"Md3PersonalityVoiceCard\";\n\n/**\n * The `sample-dialog` in Material 3 — the twin of `PersonalitySampleDialog`.\n * Two authors, two grounds: the person's turns on surface-container-high,\n * the agent's on its primary-container ground, each with the M3 bubble\n * shape (a small corner toward its author). Lines marked `fixed` carry a\n * lock and \"Same in every personality\", so the contract is visible.\n */\nexport const Md3PersonalitySampleDialog = React.forwardRef<HTMLDivElement, Md3PersonalitySampleDialogProps>(\n ({ turns, agentName = \"Assistant\", label = \"Sample dialog\", className, ...props }, ref) => (\n <div\n ref={ref}\n role=\"group\"\n aria-label={label}\n data-variant=\"sample-dialog\"\n className={cn(\"flex flex-col gap-2\", className)}\n {...props}\n >\n {turns.map((turn, i) => {\n const user = turn.from === \"user\";\n return (\n <div\n key={i}\n className={cn(\n \"max-w-[85%] px-3.5 py-2.5 text-xs leading-[18px] tracking-[0.25px]\",\n user\n ? \"self-end rounded-md-lg rounded-br-md-xs bg-md-surface-container-high text-md-on-surface\"\n : \"self-start rounded-md-lg rounded-bl-md-xs bg-md-primary-container text-md-on-primary-container\",\n )}\n >\n <span className=\"sr-only\">{user ? \"You said: \" : `${agentName} said: `}</span>\n {turn.text}\n {turn.fixed && (\n <span className=\"mt-1 flex items-center gap-1 text-[11px] font-medium tracking-[0.5px] opacity-80\">\n <Lock aria-hidden=\"true\" className=\"size-3\" />\n Same in every personality\n </span>\n )}\n </div>\n );\n })}\n </div>\n ),\n);\nMd3PersonalitySampleDialog.displayName = \"Md3PersonalitySampleDialog\";\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nucleux/md3-personality",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"description": "Material 3 Personality — choose how the agent writes while the trust language stays fixed — Nucleux agentic UI for React.",
|
|
@@ -36,8 +36,11 @@
|
|
|
36
36
|
"react-dom": ">=18"
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"@nucleux/
|
|
40
|
-
"@nucleux/
|
|
39
|
+
"@nucleux/md3-agent-avatar": "0.10.0",
|
|
40
|
+
"@nucleux/md3-button": "0.10.0",
|
|
41
|
+
"@nucleux/md3-message": "0.10.0",
|
|
42
|
+
"@nucleux/personality": "0.10.0",
|
|
43
|
+
"@nucleux/utils": "0.10.0",
|
|
41
44
|
"lucide-react": "^0.469.0"
|
|
42
45
|
},
|
|
43
46
|
"devDependencies": {
|