@antadesign/anta 0.3.16 → 0.3.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/README.md +11 -10
  2. package/dist/anta_helpers.d.ts +7 -12
  3. package/dist/anta_helpers.js +11 -3
  4. package/dist/components/ButtonCopy.d.ts +9 -6
  5. package/dist/components/ButtonCopy.js +5 -3
  6. package/dist/components/InputTime.d.ts +5 -4
  7. package/dist/components/Loader.d.ts +39 -0
  8. package/dist/components/Loader.js +33 -0
  9. package/dist/components/Progress.d.ts +17 -8
  10. package/dist/components/Progress.js +12 -9
  11. package/dist/components/Slider.d.ts +89 -0
  12. package/dist/components/Slider.js +144 -0
  13. package/dist/components/copy-props.d.ts +2 -0
  14. package/dist/components/copy-props.js +2 -1
  15. package/dist/elements/a-button.css +1 -1
  16. package/dist/elements/a-copy.d.ts +1 -1
  17. package/dist/elements/a-copy.js +103 -109
  18. package/dist/elements/a-icon.d.ts +1 -0
  19. package/dist/elements/a-icon.js +1 -0
  20. package/dist/elements/a-input-time.css +1 -1
  21. package/dist/elements/a-input-time.js +297 -377
  22. package/dist/elements/a-input.css +1 -1
  23. package/dist/elements/a-input.d.ts +0 -3
  24. package/dist/elements/a-input.js +13 -45
  25. package/dist/elements/a-loader.css +1 -0
  26. package/dist/elements/a-loader.d.ts +12 -0
  27. package/dist/elements/a-loader.js +15 -0
  28. package/dist/elements/a-progress.css +1 -1
  29. package/dist/elements/a-progress.js +32 -2
  30. package/dist/elements/a-slider.css +1 -0
  31. package/dist/elements/a-slider.d.ts +24 -0
  32. package/dist/elements/a-slider.js +479 -0
  33. package/dist/elements/copy-behavior.d.ts +3 -3
  34. package/dist/elements/index.d.ts +2 -0
  35. package/dist/elements/index.js +6 -0
  36. package/dist/general_types.d.ts +82 -6
  37. package/dist/index.d.ts +8 -1
  38. package/dist/index.js +4 -0
  39. package/dist/jsx-runtime.d.ts +3 -1
  40. package/dist/reset.css +1 -1
  41. package/dist/theme-anta.css +1 -1
  42. package/package.json +1 -1
package/README.md CHANGED
@@ -32,7 +32,7 @@ recommended; the reference theme is optional.
32
32
  | Import | Provides | Skip if… |
33
33
  |---|---|---|
34
34
  | `@antadesign/anta/tokens.css` | Six seed tokens, derived role scales (`--bg-1…5`, `--text-1…5`, `--border-1…5`), `.dark`, the 15px root size, and layer order. Override a seed to reskin its tone. | You provide those variables. |
35
- | `@antadesign/anta/reset.css` | A small reset plus Anta's heading, list, and link typography in `@layer anta`. | You use another reset and typography. |
35
+ | `@antadesign/anta/reset.css` | A small reset plus Anta's focus, heading, list, and link typography in `@layer anta`. | You use another reset and typography. |
36
36
  | `@antadesign/anta/elements` | Registers every `<a-*>` element and its CSS. Per-element entries register one; see [Registering elements](#registering-elements). | You render only on the server or register elements individually. |
37
37
  | `@antadesign/anta` | Typed React/Preact wrappers such as `Progress`, `Text`, and `Icon`. | You write `<a-*>` elements directly. |
38
38
  | `@antadesign/anta/theme-anta.css` *(optional)* | The hand-tuned reference palette. Import last to replace the seed-derived default. | You want the seed-derived or your own palette. |
@@ -224,18 +224,19 @@ To use the Antithesis fonts, register your own `@font-face` declarations and ove
224
224
 
225
225
  ## Browser support
226
226
 
227
- Anta targets evergreen browsers and ships **no baseline polyfills or feature detection**. Its floor is the [Popover API](https://developer.mozilla.org/en-US/docs/Web/API/Popover_API), used by `<a-menu>` and `<a-tooltip>`:
227
+ Anta targets evergreen browsers and ships **no baseline polyfills**. Its floor is [custom-element states](https://developer.mozilla.org/en-US/docs/Web/API/CustomStateSet), used throughout the components for their internal CSS state, alongside the [Popover API](https://developer.mozilla.org/en-US/docs/Web/API/Popover_API):
228
228
 
229
229
  | Browser | Minimum version |
230
230
  | --- | --- |
231
- | Chrome / Edge | 114 (May 2023) |
232
- | Safari | 17 (Sep 2023) |
233
- | Firefox | 125 (Apr 2024) |
234
-
235
- This is roughly [Baseline 2024](https://web.dev/baseline). Anta also relies on
236
- relative OKLCH, `:has()`, `dvh`, cascade layers, and constructable shadow DOM.
237
- Older browsers can fail hard, including `showPopover()` throwing. Gate Anta on
238
- your own support matrix when you support older browsers.
231
+ | Chrome / Edge | 125 (May 2024) |
232
+ | Safari | 17.4 (Mar 2024) |
233
+ | Firefox | 126 (May 2024) |
234
+
235
+ This is [Baseline 2024](https://web.dev/baseline). Anta also relies on relative
236
+ OKLCH, `:has()`, `dvh`, cascade layers, and constructable shadow DOM. Older
237
+ browsers can fail hard, including `:state()` being unrecognized or
238
+ `showPopover()` throwing. Gate Anta on your own support matrix when you support
239
+ older browsers.
239
240
 
240
241
  Two features progressively enhance with fallbacks: `checkVisibility()` falls
241
242
  back to `getClientRects()`, and typed CSS `attr()` supports raw
@@ -73,18 +73,13 @@ export declare const NAMED_TONES: Set<string>;
73
73
  * derives the fill/text/border curve in oklch. Named tones return `base` unchanged.
74
74
  */
75
75
  export declare function toneStyle(tone: string | undefined, varName: string, base?: React.CSSProperties): React.CSSProperties | undefined;
76
- /**
77
- * Inline-style helper for a valued `round` — the polymorphic corner-radius prop
78
- * (`true` = fully round, a `number`/length = a custom radius). Mirrors `toneStyle`:
79
- * a custom value is handed to the element via `varName` (e.g. `--button-round`), so
80
- * the element's CSS resolves `border-radius: var(--{c}-round, <default>)`. This is
81
- * the portable path — the element's `attr(round type(<length>), …)` default only
82
- * resolves on newer engines, exactly like the tone-source `attr()`.
83
- *
84
- * A `number` becomes `<n>px`; a non-empty `string` is used verbatim (so `'1rem'` /
85
- * `'50%'` work). `true` / `false` / `undefined` add nothing (presence alone → the
86
- * element's default full-round). Returns `base` unchanged when there's no value.
87
- */
76
+ /** Converts a numeric or string length to CSS text. Numbers become pixels. */
77
+ export declare function cssLength(length: number | string | undefined): string | undefined;
78
+ /** Adds a CSS length to an inline custom property. Numbers become pixels; a
79
+ * non-empty string is used verbatim. Returns `base` unchanged when absent. */
80
+ export declare function lengthStyle(length: number | string | undefined, varName: string, base?: React.CSSProperties): React.CSSProperties | undefined;
81
+ /** Inline-style helper for a valued `round`. Its boolean form leaves the
82
+ * element's default full-round radius in place. */
88
83
  export declare function roundStyle(round: boolean | number | string | undefined, varName: string, base?: React.CSSProperties): React.CSSProperties | undefined;
89
84
  /**
90
85
  * Presence flag for a `round` attribute: `''` when a radius applies, else
@@ -40,10 +40,16 @@ const NAMED_TONES = /* @__PURE__ */ new Set([
40
40
  function toneStyle(tone, varName, base) {
41
41
  return tone != null && !NAMED_TONES.has(tone) ? { ...base, [varName]: tone } : base;
42
42
  }
43
+ function cssLength(length) {
44
+ if (typeof length === "number") return `${length}px`;
45
+ return length || void 0;
46
+ }
47
+ function lengthStyle(length, varName, base) {
48
+ const value = cssLength(length);
49
+ return value ? { ...base, [varName]: value } : base;
50
+ }
43
51
  function roundStyle(round, varName, base) {
44
- if (typeof round === "number") return { ...base, [varName]: `${round}px` };
45
- if (typeof round === "string" && round !== "") return { ...base, [varName]: round };
46
- return base;
52
+ return lengthStyle(typeof round === "number" || typeof round === "string" ? round : void 0, varName, base);
47
53
  }
48
54
  function roundAttr(round) {
49
55
  return round || round === 0 ? "" : void 0;
@@ -145,10 +151,12 @@ export {
145
151
  NAMED_TONES,
146
152
  SelectableChildElement,
147
153
  anchorRect,
154
+ cssLength,
148
155
  hasChildren,
149
156
  installDismissTrigger,
150
157
  isInsideOpenMenu,
151
158
  isMenuOpen,
159
+ lengthStyle,
152
160
  nativeStateChange,
153
161
  parseOpenState,
154
162
  roundAttr,
@@ -20,11 +20,14 @@ export type ButtonCopyProps = ButtonProps & {
20
20
  form?: never;
21
21
  iconTrailing?: never;
22
22
  } & CopyTarget & {
23
- /** Where the copy glyph sits relative to the label — or `'none'` to omit it,
24
- * in which case the feedback is a ghost of the label floating up (`toast`)
25
- * plus a brief success / failure tone flash.
23
+ /** Where the copy glyph sits relative to the label — or `'none'` to omit it.
24
+ * Without a glyph, a successful copy shows a small confirmation label near
25
+ * the pointer and leaves the button unchanged.
26
26
  * @defaultValue 'leading' */
27
27
  iconPlacement?: 'leading' | 'trailing' | 'none';
28
+ /** Text in the successful no-icon confirmation.
29
+ * @defaultValue Copied */
30
+ copiedLabel?: string;
28
31
  };
29
32
  /**
30
33
  * Copy button — a `Button` preset for copy-to-clipboard. Set `copy` for a literal
@@ -37,7 +40,7 @@ export type ButtonCopyProps = ButtonProps & {
37
40
  * copy glyph to a check (success) or ✕ (failure) and retones to `success` /
38
41
  * `critical` for ~2s (a re-render, no element state — see `useCopyFeedback`).
39
42
  * `iconPlacement` puts that glyph leading (default), trailing, or `'none'`; with
40
- * `'none'` the `<a-copy>` floats a ghost of the label upward instead.
43
+ * `'none'`, `<a-copy>` shows its `Copied` confirmation instead.
41
44
  *
42
45
  * With a `label` it's a labeled button; without one it's an icon-only copy button
43
46
  * (named "Copy" for assistive tech). Everything else is a normal `Button` prop —
@@ -48,9 +51,9 @@ export type ButtonCopyProps = ButtonProps & {
48
51
  * <ButtonCopy copy="npm i @antadesign/anta" label="Copy install" />
49
52
  * <ButtonCopy copy="https://anta.design" /> // icon-only
50
53
  * <ButtonCopy copy={code} label="Copy" iconPlacement="trailing" />
51
- * <ButtonCopy copy={code} label="Copy snippet" iconPlacement="none" /> // ghost feedback
54
+ * <ButtonCopy copy={code} label="Copy snippet" iconPlacement="none" copiedLabel="Copied" />
52
55
  * <ButtonCopy copyNode=".snippet" label="Copy block" priority="tertiary" />
53
56
  * <ButtonCopy copyUrl label="Copy link" /> // copies location.href
54
57
  * ```
55
58
  */
56
- export declare const ButtonCopy: ({ icon, iconPlacement, tone, onCopied, onCopyRequest, copy, copyNode, copyUrl, copyWithUrl, label, children, "aria-label": ariaLabel, ...rest }: ButtonCopyProps) => any;
59
+ export declare const ButtonCopy: ({ icon, iconPlacement, copiedLabel, tone, onCopied, onCopyRequest, copy, copyNode, copyUrl, copyWithUrl, label, children, "aria-label": ariaLabel, ...rest }: ButtonCopyProps) => any;
@@ -5,6 +5,7 @@ import { copyElementProps, isNodeCopy } from "./copy-props";
5
5
  const ButtonCopy = ({
6
6
  icon,
7
7
  iconPlacement = "leading",
8
+ copiedLabel,
8
9
  tone,
9
10
  onCopied,
10
11
  onCopyRequest,
@@ -28,15 +29,16 @@ const ButtonCopy = ({
28
29
  copyWithUrl,
29
30
  onCopyRequest,
30
31
  onCopied: handleCopied,
31
- // Ghost feedback only makes sense when there's no glyph to swap.
32
- toast: iconPlacement === "none"
32
+ // The top-layer confirmation only appears when there is no glyph to swap.
33
+ toast: iconPlacement === "none",
34
+ copiedLabel
33
35
  });
34
36
  return /* @__PURE__ */ jsxs(
35
37
  Button,
36
38
  {
37
39
  ...iconSlot,
38
40
  label,
39
- tone: shownTone,
41
+ tone: iconPlacement === "none" ? tone : shownTone,
40
42
  "aria-label": ariaLabel ?? (hasText ? void 0 : "Copy"),
41
43
  "data-copy-node-button": isNodeCopy({ copyNode }) ? "" : void 0,
42
44
  ...rest,
@@ -84,10 +84,11 @@ export interface InputTimeProps extends BaseProps, DOMEventHandlers {
84
84
  /**
85
85
  * `<InputTime>` — a segmented wall-clock time field. One boxed input (matching
86
86
  * the other inputs) with separate hour / minute / (12-hour) AM-PM sections that
87
- * behave as one control: each is a `role="spinbutton"` — ↑/↓ steps with wrap,
88
- * ←/→ moves between them, typing digits auto-advances, and AM/PM toggles with
89
- * ↑/↓ or `a`/`p`. Renders an `<a-input-time>` web component that owns the
90
- * segments, keyboard, and form value (via `ElementInternals`).
87
+ * behave as one control: each is a native text input — ↑/↓ steps with wrap,
88
+ * ←/→ crosses segments at caret boundaries, typing digits auto-advances, and
89
+ * AM/PM accepts its locale text or `a`/`p`. Renders an `<a-input-time>` web
90
+ * component that owns the segments, navigation, and form value (via
91
+ * `ElementInternals`).
91
92
  *
92
93
  * The clock and layout follow the locale (`en-US` → 12-hour, most others 24),
93
94
  * overridable with `hour12`. The value is a 24-hour `"HH:mm"` string; controlled
@@ -0,0 +1,39 @@
1
+ import type { BaseProps } from '../general_types';
2
+ export interface LoaderProps extends BaseProps {
3
+ /** Current progress value. Omit this prop, or pass `false`, for an
4
+ * indeterminate rotating gradient. */
5
+ value?: number | false;
6
+ /** Upper bound of the range.
7
+ * @defaultValue 100 */
8
+ max?: number;
9
+ /** Width and height in pixels.
10
+ * @defaultValue 16 */
11
+ size?: number;
12
+ /** Seconds per rotation. Pass a positive number.
13
+ * @defaultValue 0.75 */
14
+ speed?: number;
15
+ /** Accessible name for a standalone loader. Without a label, the loader is
16
+ * decorative so nearby status text remains the single announcement. */
17
+ label?: string;
18
+ }
19
+ /**
20
+ * Animated, icon-sized feedback for loading work.
21
+ *
22
+ * Omit `value` for the rotating gradient. Pass `value` to fill a static circle
23
+ * to the current proportion. `shape="loader"` provides the indeterminate
24
+ * visual for string-only icon props such as `Button`'s `icon`.
25
+ *
26
+ * Requires `@antadesign/anta/elements` to be imported (client-side only) to
27
+ * register the underlying custom element.
28
+ *
29
+ * @example Indeterminate
30
+ * ```tsx
31
+ * <Loader label="Loading results" />
32
+ * ```
33
+ *
34
+ * @example Determinate
35
+ * ```tsx
36
+ * <Loader value={42} label="Uploading files" />
37
+ * ```
38
+ */
39
+ export declare const Loader: ({ value, max, size, speed, label, className, style, ...rest }: LoaderProps) => any;
@@ -0,0 +1,33 @@
1
+ import { jsx } from "@antadesign/anta/jsx-runtime";
2
+ const Loader = ({ value, max = 100, size, speed, label, className, style, ...rest }) => {
3
+ const determinate = typeof value === "number" && Number.isFinite(value);
4
+ const safeMax = Number.isFinite(max) && max > 0 ? max : 100;
5
+ const clampedValue = determinate ? Math.min(safeMax, Math.max(0, value)) : void 0;
6
+ const percentage = clampedValue != null ? clampedValue / safeMax * 100 : void 0;
7
+ const computedStyle = {
8
+ ...style,
9
+ ...size != null ? { ["--loader-size"]: `${size}px` } : {},
10
+ ...!determinate && speed != null && Number.isFinite(speed) && speed > 0 ? { ["--loader-speed"]: `${speed}s` } : {},
11
+ ...percentage != null ? { ["--loader-value"]: `${percentage}%` } : {}
12
+ };
13
+ const a11y = label != null ? {
14
+ role: "progressbar",
15
+ "aria-label": label,
16
+ "aria-valuenow": determinate ? clampedValue : void 0,
17
+ "aria-valuemin": determinate ? 0 : void 0,
18
+ "aria-valuemax": determinate ? safeMax : void 0
19
+ } : { "aria-hidden": "true" };
20
+ return /* @__PURE__ */ jsx(
21
+ "a-loader",
22
+ {
23
+ ...determinate ? { value: clampedValue } : {},
24
+ class: className,
25
+ style: computedStyle,
26
+ ...a11y,
27
+ ...rest
28
+ }
29
+ );
30
+ };
31
+ export {
32
+ Loader
33
+ };
@@ -1,7 +1,8 @@
1
1
  import type { BaseProps } from "../general_types";
2
2
  export interface ProgressProps extends BaseProps {
3
- /** Current progress value. Negative values are clamped to 0. */
4
- value: number;
3
+ /** Current progress value. Omit this prop, or pass `false`, to show
4
+ * indeterminate progress. Negative values are clamped to 0. */
5
+ value?: number | false;
5
6
  /** Upper bound of the range.
6
7
  * @defaultValue 100 */
7
8
  max?: number;
@@ -10,20 +11,23 @@ export interface ProgressProps extends BaseProps {
10
11
  * light/dark automatically.
11
12
  * @defaultValue 'neutral' */
12
13
  tone?: 'neutral' | 'brand' | 'info' | 'success' | 'warning' | 'critical' | (string & {});
14
+ /** Size variant. Scales the track and the default label row together.
15
+ * @defaultValue medium */
16
+ size?: 'small' | 'medium' | 'large';
13
17
  /** Fully-round track (`border-radius: 999px`); the fill is clipped to it. Pass a
14
18
  * `number` (px) or a CSS length string for a custom radius. */
15
19
  round?: boolean | number | string;
16
- /** Text label displayed after the percentage. When you provide custom
17
- * `children` (which replace the default label row), `label` is no longer
18
- * rendered — but it still supplies the progressbar's accessible name, so
19
- * pass it for screen readers to announce more than the bare percentage. */
20
+ /** Text label displayed after the percentage, or on its own for
21
+ * indeterminate progress. When you provide custom `children` (which replace
22
+ * the default label row), `label` is no longer rendered — but it still
23
+ * supplies the progressbar's accessible name. */
20
24
  label?: string;
21
25
  /** Right-aligned hint text (e.g. "3 of 7"). Like `label`, it's not rendered
22
26
  * when custom `children` are provided but still feeds the accessible name. */
23
27
  hint?: string;
24
28
  }
25
29
  /**
26
- * Progress indicator for displaying task completion.
30
+ * Progress indicator for task completion and indeterminate work.
27
31
  *
28
32
  * Renders an `<a-progress>` web component with an optional label area
29
33
  * showing percentage, text label, and hint.
@@ -44,9 +48,14 @@ export interface ProgressProps extends BaseProps {
44
48
  * <Progress value={42} label="Uploading files..." hint="3 of 7" />
45
49
  * ```
46
50
  *
51
+ * @example Indeterminate
52
+ * ```tsx
53
+ * <Progress label="Preparing upload..." />
54
+ * ```
55
+ *
47
56
  * @example Info tone
48
57
  * ```tsx
49
58
  * <Progress value={75} tone="info" label="Processing" />
50
59
  * ```
51
60
  */
52
- export declare const Progress: ({ value, max, tone, round, label, hint, className, style, children, ...rest }: ProgressProps) => any;
61
+ export declare const Progress: ({ value, max, tone, size, round, label, hint, className, style, children, ...rest }: ProgressProps) => any;
@@ -1,26 +1,29 @@
1
1
  import { jsx, jsxs } from "@antadesign/anta/jsx-runtime";
2
2
  import { hasChildren, toneStyle, roundStyle, roundAttr } from "../anta_helpers";
3
- const Progress = ({ value, max = 100, tone, round, label, hint, className, style, children, ...rest }) => {
4
- const percent = max > 0 ? Math.round(Math.min(100, Math.max(0, value / max * 100))) : 0;
5
- const clampedValue = max > 0 ? Math.min(max, Math.max(0, value)) : 0;
6
- const ariaLabel = [label, `${percent}%`, hint].filter(Boolean).join(" \xB7 ") || void 0;
3
+ const Progress = ({ value, max = 100, tone, size, round, label, hint, className, style, children, ...rest }) => {
4
+ const indeterminate = value == null || value === false;
5
+ const numericValue = typeof value === "number" ? value : 0;
6
+ const percent = max > 0 ? Math.round(Math.min(100, Math.max(0, numericValue / max * 100))) : 0;
7
+ const clampedValue = max > 0 ? Math.min(max, Math.max(0, numericValue)) : 0;
8
+ const ariaLabel = [label, !indeterminate && `${percent}%`, hint].filter(Boolean).join(" \xB7 ") || (indeterminate ? "Loading" : void 0);
7
9
  return /* @__PURE__ */ jsx(
8
10
  "a-progress",
9
11
  {
10
- value,
12
+ value: indeterminate ? false : numericValue,
11
13
  max,
12
14
  tone: tone && tone !== "neutral" ? tone : void 0,
15
+ size: size && size !== "medium" ? size : void 0,
13
16
  round: roundAttr(round),
14
17
  role: "progressbar",
15
- "aria-valuenow": clampedValue,
16
- "aria-valuemin": 0,
17
- "aria-valuemax": max,
18
+ "aria-valuenow": indeterminate ? void 0 : clampedValue,
19
+ "aria-valuemin": indeterminate ? void 0 : 0,
20
+ "aria-valuemax": indeterminate ? void 0 : max,
18
21
  "aria-label": ariaLabel,
19
22
  class: className,
20
23
  style: roundStyle(round, "--progress-round", toneStyle(tone, "--progress-tone-source", style)),
21
24
  ...rest,
22
25
  children: hasChildren(children) ? children : /* @__PURE__ */ jsxs("a-progress-label", { children: [
23
- /* @__PURE__ */ jsxs("a-progress-number", { children: [
26
+ !indeterminate && /* @__PURE__ */ jsxs("a-progress-number", { children: [
24
27
  percent,
25
28
  "%"
26
29
  ] }),
@@ -0,0 +1,89 @@
1
+ import type { BaseProps, DOMEventHandlers } from '../general_types';
2
+ /** A text marker displayed below the slider rail. Markers are labels only; they
3
+ * do not add dots or ticks to the rail. */
4
+ export interface SliderMarker {
5
+ value: number;
6
+ label: React.ReactNode;
7
+ }
8
+ /** Snapshot passed to `onValueChange` and `onValueCommit`. */
9
+ export interface SliderChangeAttrs {
10
+ value: number;
11
+ min: number;
12
+ max: number;
13
+ step: number;
14
+ name?: string;
15
+ }
16
+ export interface SliderProps extends BaseProps, DOMEventHandlers {
17
+ /** Visible field label, shown above the rail. A string supplies the slider's
18
+ * accessible name; give a rich label an explicit `aria-label`. */
19
+ label?: React.ReactNode;
20
+ /** Controlled value. Update it from `onValueChange`. */
21
+ value?: number;
22
+ /** Initial uncontrolled value.
23
+ * @defaultValue 0 */
24
+ defaultValue?: number;
25
+ /** Lowest permitted value.
26
+ * @defaultValue 0 */
27
+ min?: number;
28
+ /** Highest permitted value.
29
+ * @defaultValue 100 */
30
+ max?: number;
31
+ /** Smallest keyboard and drag increment.
32
+ * @defaultValue 1 */
33
+ step?: number;
34
+ /** Form field name. The current numeric value submits under this name. */
35
+ name?: string;
36
+ /** Disables pointer and keyboard interaction. */
37
+ disabled?: boolean;
38
+ /** Colour of the filled rail. Pass a named tone or a literal CSS colour for a
39
+ * one-off custom tone. The unfilled rail stays neutral.
40
+ * @defaultValue 'neutral' */
41
+ tone?: 'neutral' | 'brand' | 'info' | 'success' | 'warning' | 'critical' | (string & {});
42
+ /** Colour of the thumb stroke. Pass a named tone or a literal CSS colour for a
43
+ * one-off custom tone. Omit it to keep the thumb neutral.
44
+ * @defaultValue 'neutral' */
45
+ thumbTone?: 'neutral' | 'brand' | 'info' | 'success' | 'warning' | 'critical' | (string & {});
46
+ /** Size variant. small=24px, medium=28px, large=32px tall.
47
+ * @defaultValue 'medium' */
48
+ size?: 'small' | 'medium' | 'large';
49
+ /** Thickness of both rail segments. Numbers use pixels; strings are CSS
50
+ * lengths. Keep it no larger than the thumb diameter.
51
+ * @defaultValue 2 */
52
+ trackSize?: number | string;
53
+ /** Diameter of the thumb. Numbers use pixels; strings are CSS lengths. Keep
54
+ * it at least as large as `trackSize`.
55
+ * @defaultValue 18 */
56
+ thumbSize?: number | string;
57
+ /** Fill the thumb with its resolved border colour. This follows `thumbTone`
58
+ * and interactive states.
59
+ * @defaultValue false */
60
+ thumbFill?: boolean;
61
+ /** Fully round the rail and thumb. Pass a number (px) or CSS length string
62
+ * for a shared custom radius. */
63
+ round?: boolean | number | string;
64
+ /** Where the live value appears. `end` puts it at the right edge of the label
65
+ * row. `inline` renders `Label: value`. `thumb` keeps it above the thumb.
66
+ * @defaultValue 'end' */
67
+ valueDisplay?: 'end' | 'inline' | 'thumb' | 'none';
68
+ /** Text inserted before the live numeric value, such as `$`. */
69
+ valuePrefix?: string;
70
+ /** Text inserted after the live numeric value, such as `%` or `°C`. */
71
+ valueSuffix?: string;
72
+ /** Compact text labels positioned below the rail. They do not add dots or
73
+ * ticks to the rail. */
74
+ markers?: SliderMarker[];
75
+ /** Track press behaviour. `drag-only` starts a relative grab from the current
76
+ * value; `jump` first moves to the press position.
77
+ * @defaultValue 'drag-only' */
78
+ trackClick?: 'drag-only' | 'jump';
79
+ /** Fires on every keyboard or pointer value change. */
80
+ onValueChange?: (event: any, attrs: SliderChangeAttrs) => void;
81
+ /** Fires after a drag ends and after each keyboard value change. */
82
+ onValueCommit?: (event: any, attrs: SliderChangeAttrs) => void;
83
+ }
84
+ /**
85
+ * Slider selects one numeric value from a range. Pressing anywhere on its rail
86
+ * starts a relative drag by default, so the thumb never jumps to the press point.
87
+ * Requires `@antadesign/anta/elements` on the client.
88
+ */
89
+ export declare const Slider: ({ label, value, defaultValue, min: minProp, max: maxProp, step: stepProp, name, disabled, tone, thumbTone, size, trackSize, thumbSize, thumbFill, round, valueDisplay, valuePrefix, valueSuffix, markers, trackClick, onInput, onChange, onValueChange, onValueCommit, className, style, children, tabIndex, ...rest }: SliderProps) => any;
@@ -0,0 +1,144 @@
1
+ import { jsx, jsxs } from "@antadesign/anta/jsx-runtime";
2
+ import { toneStyle, roundStyle, roundAttr, lengthStyle, cssLength } from "../anta_helpers";
3
+ const number = (value, fallback) => Number.isFinite(value) ? value : fallback;
4
+ const isStringish = (node) => typeof node === "string" || typeof node === "number";
5
+ const bounds = (min, max) => {
6
+ const low = number(min, 0);
7
+ return { min: low, max: Math.max(low, number(max, 100)) };
8
+ };
9
+ const attrsOf = (event) => {
10
+ const element = event?.target ?? {};
11
+ return {
12
+ value: Number(element.value ?? 0),
13
+ min: Number(element.getAttribute?.("min") ?? 0),
14
+ max: Number(element.getAttribute?.("max") ?? 100),
15
+ step: Number(element.getAttribute?.("step") ?? 1),
16
+ name: element.getAttribute?.("name") ?? void 0
17
+ };
18
+ };
19
+ const Slider = ({
20
+ label,
21
+ value,
22
+ defaultValue,
23
+ min: minProp,
24
+ max: maxProp,
25
+ step: stepProp,
26
+ name,
27
+ disabled,
28
+ tone,
29
+ thumbTone,
30
+ size,
31
+ trackSize,
32
+ thumbSize,
33
+ thumbFill,
34
+ round,
35
+ valueDisplay = "end",
36
+ valuePrefix,
37
+ valueSuffix,
38
+ markers,
39
+ trackClick = "drag-only",
40
+ onInput,
41
+ onChange,
42
+ onValueChange,
43
+ onValueCommit,
44
+ className,
45
+ style,
46
+ children,
47
+ tabIndex,
48
+ ...rest
49
+ }) => {
50
+ const trackSizeValue = cssLength(trackSize);
51
+ const thumbSizeValue = cssLength(thumbSize);
52
+ const computedStyle = lengthStyle(
53
+ thumbSize,
54
+ "--anta-slider-thumb-size",
55
+ lengthStyle(
56
+ trackSize,
57
+ "--anta-slider-track-size",
58
+ roundStyle(
59
+ round,
60
+ "--slider-round",
61
+ toneStyle(thumbTone, "--slider-thumb-tone-source", toneStyle(tone, "--slider-tone-source", style))
62
+ )
63
+ )
64
+ );
65
+ const { min, max } = bounds(minProp, maxProp);
66
+ const step = number(stepProp, 1) > 0 ? number(stepProp, 1) : 1;
67
+ const explicitAriaLabel = rest["aria-label"];
68
+ const ariaLabel = (typeof explicitAriaLabel === "string" ? explicitAriaLabel : void 0) ?? (typeof label === "string" || typeof label === "number" ? String(label) : void 0);
69
+ const resolvedValueDisplay = valueDisplay === "inline" && label == null ? "end" : valueDisplay;
70
+ const markerPosition = (marker) => {
71
+ if (marker.value <= min) return "0%";
72
+ if (marker.value >= max) return "100%";
73
+ const ratio = (marker.value - min) / (max - min);
74
+ return `calc((100% - var(--anta-slider-thumb-size)) * ${ratio} + var(--anta-slider-thumb-size) / 2)`;
75
+ };
76
+ const markerAlignment = (marker) => marker.value <= min ? "start" : marker.value >= max ? "end" : void 0;
77
+ const markerStyle = (marker) => {
78
+ const markerStyle2 = {};
79
+ Object.assign(markerStyle2, { "--slider-marker-position": markerPosition(marker) });
80
+ return markerStyle2;
81
+ };
82
+ const handleInput = onInput || onValueChange ? (event) => {
83
+ const attrs = attrsOf(event);
84
+ onInput?.(event);
85
+ onValueChange?.(event, attrs);
86
+ } : void 0;
87
+ const handleChange = onChange || onValueCommit ? (event) => {
88
+ const attrs = attrsOf(event);
89
+ onChange?.(event);
90
+ onValueCommit?.(event, attrs);
91
+ } : void 0;
92
+ return /* @__PURE__ */ jsxs(
93
+ "a-slider",
94
+ {
95
+ value,
96
+ defaultvalue: defaultValue,
97
+ min,
98
+ max,
99
+ step,
100
+ name,
101
+ disabled: disabled ? "" : void 0,
102
+ tone: tone && tone !== "neutral" ? tone : void 0,
103
+ "thumb-tone": thumbTone && thumbTone !== "neutral" ? thumbTone : void 0,
104
+ size: size && size !== "medium" ? size : void 0,
105
+ "track-size": trackSizeValue,
106
+ "thumb-size": thumbSizeValue,
107
+ "thumb-fill": thumbFill ? "" : void 0,
108
+ round: roundAttr(round),
109
+ "track-click": trackClick === "jump" ? "jump" : void 0,
110
+ "value-display": resolvedValueDisplay === "end" ? void 0 : resolvedValueDisplay,
111
+ "value-prefix": valuePrefix,
112
+ "value-suffix": valueSuffix,
113
+ role: "slider",
114
+ "aria-label": ariaLabel,
115
+ tabIndex: disabled ? -1 : tabIndex ?? 0,
116
+ oninput: handleInput,
117
+ onchange: handleChange,
118
+ class: className,
119
+ style: computedStyle,
120
+ ...rest,
121
+ children: [
122
+ label != null && (isStringish(label) ? /* @__PURE__ */ jsx("span", { slot: "label", children: label }) : /* @__PURE__ */ jsx("span", { slot: "label", style: { display: "contents" }, children: label })),
123
+ markers?.map((marker, index) => {
124
+ const alignment = markerAlignment(marker);
125
+ return /* @__PURE__ */ jsx(
126
+ "span",
127
+ {
128
+ slot: "markers",
129
+ style: markerStyle(marker),
130
+ "data-slider-marker-start": alignment === "start" ? "" : void 0,
131
+ "data-slider-marker-end": alignment === "end" ? "" : void 0,
132
+ children: marker.label
133
+ },
134
+ `${marker.value}-${index}`
135
+ );
136
+ }),
137
+ children
138
+ ]
139
+ }
140
+ );
141
+ };
142
+ export {
143
+ Slider
144
+ };
@@ -51,6 +51,7 @@ type CopyElementInput = {
51
51
  onCopyRequest?: () => void;
52
52
  onCopied?: (ok: boolean) => void;
53
53
  toast?: boolean;
54
+ copiedLabel?: string;
54
55
  };
55
56
  /** Project the copy-target props onto `<a-copy>` attributes + event handlers.
56
57
  * Shared by `ButtonCopy` / `MenuItemCopy` so the mapping (and the cross-renderer
@@ -61,6 +62,7 @@ export declare function copyElementProps(p: CopyElementInput): {
61
62
  readonly 'copy-url': "" | undefined;
62
63
  readonly 'copy-with-url': "" | undefined;
63
64
  readonly toast: "" | undefined;
65
+ readonly 'copied-label': string | undefined;
64
66
  readonly oncopydone: ((e: any) => void) | undefined;
65
67
  readonly oncopyrequest: (() => void) | undefined;
66
68
  };
@@ -1,12 +1,13 @@
1
1
  import { nativeStateChange } from "../anta_helpers";
2
2
  function copyElementProps(p) {
3
- const { copy, copyNode, copyUrl, copyWithUrl, onCopyRequest, onCopied, toast } = p;
3
+ const { copy, copyNode, copyUrl, copyWithUrl, onCopyRequest, onCopied, toast, copiedLabel } = p;
4
4
  return {
5
5
  copy: copy != null ? copy : void 0,
6
6
  "copy-node": copyNode === true ? "" : typeof copyNode === "string" ? copyNode : void 0,
7
7
  "copy-url": copyUrl ? "" : void 0,
8
8
  "copy-with-url": copyWithUrl ? "" : void 0,
9
9
  toast: toast ? "" : void 0,
10
+ "copied-label": copiedLabel,
10
11
  oncopydone: onCopied ? (e) => onCopied(nativeStateChange(e).detail?.ok ?? false) : void 0,
11
12
  oncopyrequest: onCopyRequest ? () => onCopyRequest() : void 0
12
13
  };