@synopackageland/ui 0.14.0 → 0.14.2

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/CHANGELOG.md CHANGED
@@ -1,5 +1,18 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.14.2 (2026-10-22)
4
+
5
+ Additive only: existing props, defaults and DOM stay as they were.
6
+
7
+ - `LoadingMask`: `delay` (ms, default 0) shows the mask only once `loading` has lasted that long, so a quick load does not flash it; it hides as soon as `loading` ends. The region is `aria-busy` from the start.
8
+
9
+ ## 0.14.1 (2026-10-22)
10
+
11
+ Additive only: existing props, defaults and DOM stay as they were.
12
+
13
+ - Add `CopyButton`: a copy action whose result shows on the button itself. A press copies `text` (a string or a function read at the press), turns the button to the success colour with a check, and fades back after 1.8s; a failure does the same in the danger colour with a cross and emits `failed(text)` for a manual-copy fallback. The tooltip and accessible name stay the action; a visually hidden polite live region announces the result. Icon-only or `labelled`, `ghost`/`secondary`/`primary`, `sm`/`md`, an optional `icon`, and `words` for the announcements. Reduced motion keeps only the colour change.
14
+ - New string in all nine built-in languages: "Couldn't copy".
15
+
3
16
  ## 0.14.0 (2026-10-22)
4
17
 
5
18
  Additive only: existing props, defaults and DOM stay as they were.
package/README.md CHANGED
@@ -468,7 +468,7 @@ Density can be switched per application subtree:
468
468
 
469
469
  Primitives:
470
470
 
471
- - Button / IconButton
471
+ - Button / IconButton / CopyButton
472
472
  - Input / Textarea
473
473
  - Checkbox / CheckboxGroup / RadioGroup / Switch
474
474
  - Select
@@ -628,7 +628,7 @@ phone; use `DataGrid` for anything a user searches or arranges.
628
628
 
629
629
  ### Loading
630
630
 
631
- `Spinner` is the DSM ring (`size` is the box in px, default 24). `LoadingMask` wraps content and covers it with a white 60% mask and a centred message box while `loading`; `LoadingArea` fills its container (give the parent a height) and centres the indicator, for whole-page or whole-panel waits. `Button loading` shows the 16px ring inline. Do not place a bare `Spinner` in a block container and expect it to be centred: use `LoadingArea`.
631
+ `Spinner` is the DSM ring (`size` is the box in px, default 24). `LoadingMask` wraps content and covers it with a white 60% mask and a centred message box while `loading` (`delay` in ms holds the mask back so a quick load never flashes it; the region is `aria-busy` at once, so disable the actions it gates yourself); `LoadingArea` fills its container (give the parent a height) and centres the indicator, for whole-page or whole-panel waits. `Button loading` shows the 16px ring inline. Do not place a bare `Spinner` in a block container and expect it to be centred: use `LoadingArea`.
632
632
 
633
633
  ### Toolbar
634
634
 
@@ -856,7 +856,21 @@ Copy text with `writeClipboard(text)`, which resolves `true` once copied and
856
856
  `false` when the page cannot copy. It tries the Clipboard API, which a DSM app
857
857
  window (a frame without `clipboard-write`) or a page outside a secure context
858
858
  refuses, then the legacy copy command; `navigator.clipboard.writeText` alone
859
- fails there. `PathDisplay` and `CopyCutField` use it.
859
+ fails there. `PathDisplay`, `CopyCutField` and `CopyButton` use it.
860
+
861
+ `CopyButton` is a copy action that shows its result on the button itself: on
862
+ a press it copies `text` (a string, or a function read at the press; `undefined`
863
+ copies nothing), takes the success colour and a check, holds it for 1.8s and
864
+ fades back; when the page cannot copy it does the same in the danger colour with
865
+ a cross and emits `failed(text)`, so the app can show the text selected in a
866
+ `CopyCutField` for copying by hand. Nothing is added beside or under it. `label`
867
+ (default "Copy") stays its tooltip and accessible name; a visually hidden polite
868
+ live region announces "Copied" or "Couldn't copy" (`words` replaces them). It is
869
+ an icon button, or with `labelled` an icon and the label; `icon` replaces the
870
+ copy icon, and `variant` (`ghost`, `secondary`, `primary`) and `size` (`sm`, the
871
+ default, or `md`) follow `IconButton` and `Button`. Under reduced motion only the
872
+ colour changes. Attributes and classes go to the button; the button carries
873
+ `data-copy-state` (`copied`, `failed`, then `settling` while it fades back).
860
874
 
861
875
  FilePicker retains browser `File[]` semantics. Built-in `locale` values are
862
876
  `en`, `zh-TW`, `zh-CN`, `ja`, `ko`, `de`, `fr`, `es`, `it`; an explicit picker
@@ -0,0 +1,36 @@
1
+ import { Component } from 'vue';
2
+ export type CopyButtonText = string | (() => string | undefined | Promise<string | undefined>);
3
+ export interface CopyButtonWords {
4
+ copied?: string;
5
+ failed?: string;
6
+ }
7
+ type __VLS_Props = {
8
+ text: CopyButtonText;
9
+ /** The action's name: the tooltip, the accessible name and, when `labelled`, the visible text. Defaults to "Copy". */
10
+ label?: string;
11
+ /** What the live region announces; defaults to the built-in "Copied" and "Couldn't copy". */
12
+ words?: CopyButtonWords;
13
+ /** The idle icon; the default is a copy icon. */
14
+ icon?: Component;
15
+ labelled?: boolean;
16
+ variant?: 'ghost' | 'secondary' | 'primary';
17
+ size?: 'sm' | 'md';
18
+ disabled?: boolean;
19
+ };
20
+ declare const __VLS_export: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
21
+ copied: (text: string) => any;
22
+ failed: (text: string) => any;
23
+ }, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{
24
+ onCopied?: ((text: string) => any) | undefined;
25
+ onFailed?: ((text: string) => any) | undefined;
26
+ }>, {
27
+ label: string;
28
+ size: "sm" | "md";
29
+ variant: "ghost" | "secondary" | "primary";
30
+ disabled: boolean;
31
+ icon: Component;
32
+ words: CopyButtonWords;
33
+ labelled: boolean;
34
+ }, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
35
+ declare const _default: typeof __VLS_export;
36
+ export default _default;
@@ -1,6 +1,8 @@
1
1
  type __VLS_Props = {
2
2
  loading?: boolean;
3
3
  text?: string;
4
+ /** Milliseconds `loading` must last before the overlay shows, so a quick load does not flash it. The region is `aria-busy` at once. */
5
+ delay?: number;
4
6
  };
5
7
  declare var __VLS_1: {};
6
8
  type __VLS_Slots = {} & {
@@ -9,6 +11,7 @@ type __VLS_Slots = {} & {
9
11
  declare const __VLS_base: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
10
12
  text: string;
11
13
  loading: boolean;
14
+ delay: number;
12
15
  }, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
13
16
  declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
14
17
  declare const _default: typeof __VLS_export;
@@ -158,6 +158,7 @@ export declare const englishUiText: {
158
158
  readonly "Path: {path}": "Path: {path}";
159
159
  readonly Copied: "Copied";
160
160
  readonly "Couldn't copy. Select the text and copy it manually.": "Couldn't copy. Select the text and copy it manually.";
161
+ readonly "Couldn't copy": "Couldn't copy";
161
162
  };
162
163
  export type UiTextKey = keyof typeof englishUiText;
163
164
  export type UiTranslator = (key: UiTextKey, values?: Record<string, string | number>) => string;
package/dist/index.d.ts CHANGED
@@ -137,6 +137,8 @@ export { default as FilePicker } from './components/composite/file-picker/FilePi
137
137
  export type { FileRejection } from './components/composite/file-picker/FilePicker.vue';
138
138
  export { default as CopyCutField } from './components/composite/copy-cut-field/CopyCutField.vue';
139
139
  export { default as PathDisplay } from './components/composite/path-display/PathDisplay.vue';
140
+ export { default as CopyButton } from './components/composite/copy-button/CopyButton.vue';
141
+ export type { CopyButtonText, CopyButtonWords } from './components/composite/copy-button/CopyButton.vue';
140
142
  export type { CopyCutFieldAutosize } from './components/composite/copy-cut-field/CopyCutField.vue';
141
143
  export { default as DataView } from './components/composite/data-view/DataView.vue';
142
144
  export { default as VirtualList } from './components/composite/virtual-list/VirtualList.vue';