@mlola-ui/registry 1.0.6 → 1.0.8
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/components/accordion.json +2 -2
- package/components/activity-heatmap.json +1 -1
- package/components/alert.json +1 -1
- package/components/app-shell.json +1 -1
- package/components/badge.json +1 -1
- package/components/breadcrumb.json +1 -1
- package/components/button.json +5 -3
- package/components/calendar.json +1 -1
- package/components/carousel.json +2 -2
- package/components/checkbox.json +1 -1
- package/components/color-picker.json +1 -1
- package/components/combobox.json +1 -1
- package/components/command-menu.json +1 -1
- package/components/context-menu.json +2 -2
- package/components/copy-button.json +95 -0
- package/components/date-picker.json +1 -1
- package/components/dropdown-menu.json +2 -2
- package/components/dropzone.json +1 -1
- package/components/hover-card.json +1 -1
- package/components/modal.json +2 -2
- package/components/number-input.json +1 -1
- package/components/pagination.json +1 -1
- package/components/password-input.json +75 -0
- package/components/popover.json +1 -1
- package/components/segmented-control.json +1 -1
- package/components/select.json +2 -2
- package/components/sheet.json +2 -2
- package/components/slider.json +1 -1
- package/components/spinner.json +64 -0
- package/components/stepper.json +1 -1
- package/components/tabs.json +1 -1
- package/components/tag-input.json +1 -1
- package/components/time-picker.json +1 -1
- package/components/timeline.json +1 -1
- package/components/toast.json +5 -3
- package/components/tour.json +2 -2
- package/generated/catalog.ts +235 -42
- package/generated/examples.json +268 -8
- package/index.json +20 -2
- package/package.json +1 -1
- package/snapshot/index.json +288 -47
- package/snapshot/items/components/accordion.json +2 -2
- package/snapshot/items/components/activity-heatmap.json +1 -1
- package/snapshot/items/components/alert.json +1 -1
- package/snapshot/items/components/app-shell.json +1 -1
- package/snapshot/items/components/badge.json +1 -1
- package/snapshot/items/components/breadcrumb.json +1 -1
- package/snapshot/items/components/button.json +5 -3
- package/snapshot/items/components/calendar.json +1 -1
- package/snapshot/items/components/carousel.json +2 -2
- package/snapshot/items/components/checkbox.json +1 -1
- package/snapshot/items/components/color-picker.json +1 -1
- package/snapshot/items/components/combobox.json +1 -1
- package/snapshot/items/components/command-menu.json +1 -1
- package/snapshot/items/components/context-menu.json +2 -2
- package/snapshot/items/components/copy-button.json +95 -0
- package/snapshot/items/components/date-picker.json +1 -1
- package/snapshot/items/components/dropdown-menu.json +2 -2
- package/snapshot/items/components/dropzone.json +1 -1
- package/snapshot/items/components/hover-card.json +1 -1
- package/snapshot/items/components/modal.json +2 -2
- package/snapshot/items/components/number-input.json +1 -1
- package/snapshot/items/components/pagination.json +1 -1
- package/snapshot/items/components/password-input.json +75 -0
- package/snapshot/items/components/popover.json +1 -1
- package/snapshot/items/components/segmented-control.json +1 -1
- package/snapshot/items/components/select.json +2 -2
- package/snapshot/items/components/sheet.json +2 -2
- package/snapshot/items/components/slider.json +1 -1
- package/snapshot/items/components/spinner.json +64 -0
- package/snapshot/items/components/stepper.json +1 -1
- package/snapshot/items/components/tabs.json +1 -1
- package/snapshot/items/components/tag-input.json +1 -1
- package/snapshot/items/components/time-picker.json +1 -1
- package/snapshot/items/components/timeline.json +1 -1
- package/snapshot/items/components/toast.json +5 -3
- package/snapshot/items/components/tour.json +2 -2
- package/snapshot/source/packages/components/_internal/clipboard.ts +31 -0
- package/snapshot/source/packages/components/activity-heatmap/activity-heatmap.tsx +2 -2
- package/snapshot/source/packages/components/button/button.tsx +2 -1
- package/snapshot/source/packages/components/copy-button/copy-button.tsx +59 -0
- package/snapshot/source/packages/components/password-input/password-input.tsx +118 -0
- package/snapshot/source/packages/components/spinner/spinner.tsx +36 -0
- package/snapshot/source/packages/components/toast/toast.tsx +2 -1
- package/snapshot/source-manifest.json +7 -3
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { passwordStrength } from "@mlola-ui/behavior/logic";
|
|
5
|
+
import { IconEye, IconEyeOff } from "@mlola-ui/icons";
|
|
6
|
+
import { Input, type InputProps } from "../input/input";
|
|
7
|
+
|
|
8
|
+
export type PasswordStrength = ReturnType<typeof passwordStrength>;
|
|
9
|
+
|
|
10
|
+
export interface PasswordInputProps extends Omit<InputProps, "type" | "trailing"> {
|
|
11
|
+
/**
|
|
12
|
+
* Show how strong a new password is while it is typed. For a sign-in
|
|
13
|
+
* field, leave it off: the person is recalling a password, not choosing one.
|
|
14
|
+
*/
|
|
15
|
+
strength?: boolean;
|
|
16
|
+
/** The length below which a password is weak. */
|
|
17
|
+
minLength?: number;
|
|
18
|
+
/** The length at which a password is strong. */
|
|
19
|
+
strongLength?: number;
|
|
20
|
+
/** What the meter says for each level: guidance first, then a verdict with the next step. */
|
|
21
|
+
strengthHints?: Partial<Record<PasswordStrength, React.ReactNode>>;
|
|
22
|
+
/** The toggle's accessible name. Its pressed state says whether the password shows. */
|
|
23
|
+
toggleLabel?: string;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const HINTS = (min: number): Record<PasswordStrength, React.ReactNode> => ({
|
|
27
|
+
empty: `Use ${min} or more characters.`,
|
|
28
|
+
weak: (
|
|
29
|
+
<>
|
|
30
|
+
<strong>Too short.</strong> Use {min} or more characters.
|
|
31
|
+
</>
|
|
32
|
+
),
|
|
33
|
+
medium: (
|
|
34
|
+
<>
|
|
35
|
+
<strong>Good.</strong> Longer, or mixed symbols, is stronger.
|
|
36
|
+
</>
|
|
37
|
+
),
|
|
38
|
+
strong: <strong>Strong password.</strong>,
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* A password field with a show and hide toggle, and, for a new password, a
|
|
43
|
+
* meter that says how strong it is and what would make it stronger. The
|
|
44
|
+
* strength is the same shared decision the framework-free runtime uses.
|
|
45
|
+
*/
|
|
46
|
+
const PasswordInput = React.forwardRef<HTMLInputElement, PasswordInputProps>(
|
|
47
|
+
(
|
|
48
|
+
{
|
|
49
|
+
strength: showStrength = false,
|
|
50
|
+
minLength = 8,
|
|
51
|
+
strongLength = 12,
|
|
52
|
+
strengthHints,
|
|
53
|
+
toggleLabel = "Show password",
|
|
54
|
+
value,
|
|
55
|
+
defaultValue,
|
|
56
|
+
onChange,
|
|
57
|
+
autoComplete,
|
|
58
|
+
"aria-describedby": describedBy,
|
|
59
|
+
...props
|
|
60
|
+
},
|
|
61
|
+
ref,
|
|
62
|
+
) => {
|
|
63
|
+
const [visible, setVisible] = React.useState(false);
|
|
64
|
+
const [typed, setTyped] = React.useState(String(defaultValue ?? ""));
|
|
65
|
+
const current = value === undefined ? typed : String(value);
|
|
66
|
+
const level = passwordStrength(current, { min: minLength, strong: strongLength });
|
|
67
|
+
const meterId = React.useId();
|
|
68
|
+
const hints = { ...HINTS(minLength), ...strengthHints };
|
|
69
|
+
|
|
70
|
+
return (
|
|
71
|
+
<div className="ml-password-input">
|
|
72
|
+
<Input
|
|
73
|
+
ref={ref}
|
|
74
|
+
{...props}
|
|
75
|
+
type={visible ? "text" : "password"}
|
|
76
|
+
value={value}
|
|
77
|
+
defaultValue={defaultValue}
|
|
78
|
+
autoComplete={autoComplete ?? (showStrength ? "new-password" : "current-password")}
|
|
79
|
+
// A password is not a word: no autocorrect, no capital letter at the start.
|
|
80
|
+
autoCapitalize="none"
|
|
81
|
+
autoCorrect="off"
|
|
82
|
+
spellCheck={false}
|
|
83
|
+
aria-describedby={[describedBy, showStrength ? meterId : null].filter(Boolean).join(" ") || undefined}
|
|
84
|
+
onChange={(event) => {
|
|
85
|
+
if (value === undefined) setTyped(event.target.value);
|
|
86
|
+
onChange?.(event);
|
|
87
|
+
}}
|
|
88
|
+
trailing={
|
|
89
|
+
<button
|
|
90
|
+
type="button"
|
|
91
|
+
className="ml-password-input-toggle"
|
|
92
|
+
aria-label={toggleLabel}
|
|
93
|
+
aria-pressed={visible}
|
|
94
|
+
data-hit="expand"
|
|
95
|
+
disabled={props.disabled}
|
|
96
|
+
onClick={() => setVisible((shown) => !shown)}
|
|
97
|
+
>
|
|
98
|
+
{visible ? <IconEyeOff aria-hidden="true" size="1em" /> : <IconEye aria-hidden="true" size="1em" />}
|
|
99
|
+
</button>
|
|
100
|
+
}
|
|
101
|
+
/>
|
|
102
|
+
{showStrength ? (
|
|
103
|
+
<div id={meterId} className="ml-password-input-strength" data-strength={level} aria-live="polite">
|
|
104
|
+
<span className="ml-password-input-meter" aria-hidden="true">
|
|
105
|
+
<span />
|
|
106
|
+
<span />
|
|
107
|
+
<span />
|
|
108
|
+
</span>
|
|
109
|
+
<p>{hints[level]}</p>
|
|
110
|
+
</div>
|
|
111
|
+
) : null}
|
|
112
|
+
</div>
|
|
113
|
+
);
|
|
114
|
+
},
|
|
115
|
+
);
|
|
116
|
+
PasswordInput.displayName = "PasswordInput";
|
|
117
|
+
|
|
118
|
+
export { PasswordInput };
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { cx } from "../_internal/react";
|
|
5
|
+
|
|
6
|
+
export type SpinnerSize = "sm" | "md" | "lg";
|
|
7
|
+
|
|
8
|
+
export interface SpinnerProps extends Omit<React.HTMLAttributes<HTMLSpanElement>, "children"> {
|
|
9
|
+
size?: SpinnerSize;
|
|
10
|
+
/**
|
|
11
|
+
* What is loading, spoken to screen readers ("Loading results"). Leave it
|
|
12
|
+
* out when visible text beside the spinner already says so, as in a busy
|
|
13
|
+
* button; the spinner is then decorative.
|
|
14
|
+
*/
|
|
15
|
+
label?: string;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Work in progress whose end is unknown. It takes the color of the text
|
|
20
|
+
* around it, so it reads on any surface and inside any control.
|
|
21
|
+
*/
|
|
22
|
+
const Spinner = React.forwardRef<HTMLSpanElement, SpinnerProps>(({ size = "md", label, className, ...props }, ref) => (
|
|
23
|
+
<span
|
|
24
|
+
ref={ref}
|
|
25
|
+
role={label ? "status" : undefined}
|
|
26
|
+
aria-hidden={label ? undefined : true}
|
|
27
|
+
data-size={size}
|
|
28
|
+
className={cx("ml-spinner", className)}
|
|
29
|
+
{...props}
|
|
30
|
+
>
|
|
31
|
+
{label ? <span className="ml-visually-hidden">{label}</span> : null}
|
|
32
|
+
</span>
|
|
33
|
+
));
|
|
34
|
+
Spinner.displayName = "Spinner";
|
|
35
|
+
|
|
36
|
+
export { Spinner };
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
import * as React from "react";
|
|
4
4
|
import { IconCircleCheck, IconCircleX, IconInfo, IconTriangleAlert, IconX } from "@mlola-ui/icons";
|
|
5
5
|
import { cx } from "../_internal/react";
|
|
6
|
+
import { Spinner } from "../spinner/spinner";
|
|
6
7
|
|
|
7
8
|
/** The meaning of the message, from the theme's color roles. */
|
|
8
9
|
export type ToastTone = "neutral" | "info" | "success" | "warning" | "danger";
|
|
@@ -193,7 +194,7 @@ function ToastCard({ item, paused }: { item: ToastItem; paused: boolean }) {
|
|
|
193
194
|
}, [paused, item.closing, item.duration, item.id, item.revision]);
|
|
194
195
|
|
|
195
196
|
const urgent = item.tone === "danger" || item.tone === "warning";
|
|
196
|
-
const icon = item.loading ? <
|
|
197
|
+
const icon = item.loading ? <Spinner /> : item.icon === undefined ? TONE_ICONS[item.tone] : item.icon;
|
|
197
198
|
|
|
198
199
|
return (
|
|
199
200
|
<div className="ml-toast-slot" data-state={item.closing ? "closed" : "open"}>
|
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"packages/components/_internal/anchor.ts": "sha256-OPm/4Jf4UUo8IG+/4TAKpGDHtYpvxvGwyq3/RSZQIGc=",
|
|
3
|
+
"packages/components/_internal/clipboard.ts": "sha256-0y5p88CTXWuOrUYlC5J4XP1VCrOwkx9jYWVHmD2LouQ=",
|
|
3
4
|
"packages/components/_internal/dialog.ts": "sha256-796y3oNOVWarLvICTdi+d0/2axqSrzLVJiyBeh9X7bU=",
|
|
4
5
|
"packages/components/_internal/floating.ts": "sha256-+WxgC4CtAlSr2qA1EkoDTgto535XLIPsvtOfdOK6CHk=",
|
|
5
6
|
"packages/components/_internal/match.ts": "sha256-nKBpKWeow5ubAHUhOW8yOjlrKs0lqYdjbaYYfE8VoII=",
|
|
6
7
|
"packages/components/_internal/react.ts": "sha256-SH63/haiB4Q93uFjMIMe5xZbaxENu3VI+GcidV8HELM=",
|
|
7
8
|
"packages/components/_internal/scroll.ts": "sha256-/YxhPPJa6Iax4q5eEs8dmpQp634TbvB+421MphEyscQ=",
|
|
8
9
|
"packages/components/accordion/accordion.tsx": "sha256-0ALaLJd1fvj8Vbx86HLBKm3qUItrtwbrGJTykVfNSMg=",
|
|
9
|
-
"packages/components/activity-heatmap/activity-heatmap.tsx": "sha256-
|
|
10
|
+
"packages/components/activity-heatmap/activity-heatmap.tsx": "sha256-IAcU8FLAJbgKAS+2X+mt6PMqJBzxr4QVdwsVAl67BH4=",
|
|
10
11
|
"packages/components/activity-heatmap/calendar.ts": "sha256-NB+AjXY5Xc+KzR8MMTRBgZxdzOeoHhkW0KQOW7WJPuQ=",
|
|
11
12
|
"packages/components/alert/alert.tsx": "sha256-j680akXvCIh4MTVnUo79acvVrv51XyQ3UBJ5FBAy8Dw=",
|
|
12
13
|
"packages/components/app-shell/app-shell.tsx": "sha256-XAq82XOTH3ZR+hxTkYFu8P7Ih2aI6ERy/TpXc2VMUwM=",
|
|
13
14
|
"packages/components/avatar/avatar.tsx": "sha256-EjqC8ytKqRtsTVdK6vncaDfhO/i7ICe+jwaYCg5bjIw=",
|
|
14
15
|
"packages/components/badge/badge.tsx": "sha256-flEH8S2jZ/64n3Y/ROhC9+9rvF7wXaN0xLcMMwqNOVQ=",
|
|
15
16
|
"packages/components/breadcrumb/breadcrumb.tsx": "sha256-Mt9mvmwwDgdp5/+mj5byIrh8+hicsp7R6UcvUlK0yog=",
|
|
16
|
-
"packages/components/button/button.tsx": "sha256-
|
|
17
|
+
"packages/components/button/button.tsx": "sha256-sXVANbGeFSYPHpiWuPvHHqMoPjG0zl0HSsKEdTgl5ME=",
|
|
17
18
|
"packages/components/calendar/calendar.tsx": "sha256-rWiS4YAueZfVoo6j5Fi3uN7A+yApe5U6HMm1woTVjys=",
|
|
18
19
|
"packages/components/calendar/dates.ts": "sha256-mygYkoC70av2ZQ0vkxf885trwW97Wd10I4dptYQe+4A=",
|
|
19
20
|
"packages/components/card/card.tsx": "sha256-aMKbv5DWYYWq7GZAFR9O1fuYE0H61WCjkvEbRMOd894=",
|
|
@@ -24,6 +25,7 @@
|
|
|
24
25
|
"packages/components/combobox/combobox.tsx": "sha256-CvuYc/hJoS7yw6QM9vv1SIkwflx0Kwd95UjchtC+AOs=",
|
|
25
26
|
"packages/components/command-menu/command-menu.tsx": "sha256-mF1z92yrPY609pjx5Dt1l5EhGHl9EWV8F8Sq0hyJRw4=",
|
|
26
27
|
"packages/components/context-menu/context-menu.tsx": "sha256-YgYsIzvLGFcJG1XX5zFJwrid5Z1Kn0lyWVzmLKmbMVU=",
|
|
28
|
+
"packages/components/copy-button/copy-button.tsx": "sha256-6fvfifoiDOtW+WxKWon4SGEn3THtERuCX2hqGSZDtVM=",
|
|
27
29
|
"packages/components/date-picker/date-picker.tsx": "sha256-rsmDweD3RVfKTXR2i+/pnTb/MsrDAZXmHAYBvcUGxig=",
|
|
28
30
|
"packages/components/dropdown-menu/dropdown-menu.tsx": "sha256-xgybCu9HBxIieafu5CjAtY4aCOQoaAj/VUCH6D6vLP8=",
|
|
29
31
|
"packages/components/dropzone/dropzone.tsx": "sha256-tHCCpEWE6839UeLOszTo+R2vAL4Sp9UxuRdLkFLfnq4=",
|
|
@@ -36,6 +38,7 @@
|
|
|
36
38
|
"packages/components/number-input/number.ts": "sha256-IrHCQrEhI5ein9ifMFuSViSoxQUBoT3tNmmCu/paGGM=",
|
|
37
39
|
"packages/components/otp-input/otp-input.tsx": "sha256-QURn8g5HqCQXBTdeENPbVxoPlqs3ZtoAPLRlFjQDxmI=",
|
|
38
40
|
"packages/components/pagination/pagination.tsx": "sha256-FBwk8tq4JcsK2D0dlWEYiDSRx3owgBmGzEIlVRaNBoE=",
|
|
41
|
+
"packages/components/password-input/password-input.tsx": "sha256-oY//vTILhUicJyfAWZrSUTl8WWsf4P2S1Bh0x4OxwLs=",
|
|
39
42
|
"packages/components/popover/popover.tsx": "sha256-/kTiAuFklU4IuP97XaiCUGdEpKtNyMPLPS359mfzPHw=",
|
|
40
43
|
"packages/components/priority-icon/labels.ts": "sha256-zhmJIb7/gS16wU+xCJ7hkReBi9q5RI3SMwdjkJvvvKU=",
|
|
41
44
|
"packages/components/priority-icon/priority-icon.tsx": "sha256-3D6hFRpht3YuWouLhakE2DFdldavmJx0B/povEDwrtQ=",
|
|
@@ -48,6 +51,7 @@
|
|
|
48
51
|
"packages/components/sheet/sheet.tsx": "sha256-EIn3OeRDmXGHbYf/uihRh8aw3LmzarIFiyC9DUsL1jg=",
|
|
49
52
|
"packages/components/skeleton/skeleton.tsx": "sha256-2Fk72NbLr3+CrXH7jGbHNsc3t+vskMqSyySe/UwbGCs=",
|
|
50
53
|
"packages/components/slider/slider.tsx": "sha256-l+VrBqPYHIIcemiVixxwDxNDB0HEMmYRZekx/H5HroQ=",
|
|
54
|
+
"packages/components/spinner/spinner.tsx": "sha256-FZQmcGkQ8N0485n9bYsLTpTnolbM729YKjkQrXriz9A=",
|
|
51
55
|
"packages/components/status-icon/labels.ts": "sha256-EE8q+geQBbJUs7I3RmaHZnPwn7Vjk2GjCfxvI4ruXKM=",
|
|
52
56
|
"packages/components/status-icon/status-icon.tsx": "sha256-TtrTeoePyfH1VhKuWC0v12FuwfgND1CHnH5x8fyf4AM=",
|
|
53
57
|
"packages/components/stepper/stepper.tsx": "sha256-uI/dRmkbijlixHiGUceWcpaDzpEixrzQ1UTmoPbGZAY=",
|
|
@@ -58,7 +62,7 @@
|
|
|
58
62
|
"packages/components/time-picker/time-picker.tsx": "sha256-og8Cbf+e8oFYewfagUgjRzLHSIIlAZh+1OpAn9yNq70=",
|
|
59
63
|
"packages/components/time-picker/times.ts": "sha256-V/4uqFZPn9gVnyx8cB9vwp/RocmTYaPmLxjfy8DPQOI=",
|
|
60
64
|
"packages/components/timeline/timeline.tsx": "sha256-nVg7lBcAUAzqEb0YrHagJXSaHE2aWWE9bUbQMWQY6PU=",
|
|
61
|
-
"packages/components/toast/toast.tsx": "sha256-
|
|
65
|
+
"packages/components/toast/toast.tsx": "sha256-f0DwN0XuV46fSsQf3i9RJcfQbAs2mSz7A8UJoIIICHg=",
|
|
62
66
|
"packages/components/toggle/toggle.tsx": "sha256-8qPHeSliHNdzQS7OLJ47BrvRR75MYyUGJlK4s21XS/U=",
|
|
63
67
|
"packages/components/tooltip/tooltip.tsx": "sha256-NbaOUmlUbBlUIdovchrWwH2QqzuvXB97DjnJnrHf4Gc=",
|
|
64
68
|
"packages/components/tour/tour.tsx": "sha256-mrAE8aVDBVIibGvQah9Gh3mzIiWDFxB6aObzqFo5xXU=",
|