@antadesign/anta 0.3.16 → 0.3.17

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.
@@ -4,6 +4,7 @@ import "./a-copy.css";
4
4
  const BUTTON_HOST = "a-button, button, [role=button]";
5
5
  const MENU_HOST = "a-menu-item, [role=menuitem]";
6
6
  const ANY_HOST = `${BUTTON_HOST}, ${MENU_HOST}`;
7
+ const pointerOrigins = /* @__PURE__ */ new WeakMap();
7
8
  function copyChild(host) {
8
9
  return host?.querySelector(":scope > a-copy") ?? null;
9
10
  }
@@ -12,13 +13,20 @@ function hostBlocked(host) {
12
13
  }
13
14
  function installCopyDelegation(doc) {
14
15
  if (!doc || doc.hasCopyDelegation) return;
15
- const preRequest = (target) => {
16
+ const preRequest = (target, origin) => {
16
17
  const host = target?.closest?.(ANY_HOST);
17
18
  if (!host || hostBlocked(host)) return;
18
19
  const el = copyChild(host);
19
- if (el) emitCopyRequest(el);
20
+ if (!el) return;
21
+ if (origin) pointerOrigins.set(el, origin);
22
+ else pointerOrigins.delete(el);
23
+ emitCopyRequest(el);
20
24
  };
21
- doc.addEventListener("pointerdown", (e) => preRequest(e.target), true);
25
+ doc.addEventListener(
26
+ "pointerdown",
27
+ (e) => preRequest(e.target, { x: e.clientX, y: e.clientY }),
28
+ true
29
+ );
22
30
  doc.addEventListener(
23
31
  "keydown",
24
32
  (e) => {
@@ -32,7 +40,12 @@ function installCopyDelegation(doc) {
32
40
  (e) => {
33
41
  const host = e.target?.closest?.(BUTTON_HOST);
34
42
  if (!host || hostBlocked(host)) return;
35
- copyChild(host)?.activate();
43
+ const el = copyChild(host);
44
+ if (!el) return;
45
+ if (e.detail)
46
+ pointerOrigins.set(el, { x: e.clientX, y: e.clientY });
47
+ else pointerOrigins.delete(el);
48
+ el.activate();
36
49
  },
37
50
  true
38
51
  );
@@ -47,131 +60,112 @@ function installCopyDelegation(doc) {
47
60
  );
48
61
  doc.hasCopyDelegation = true;
49
62
  }
50
- const GHOST_MS = 650;
51
- const GHOST_TEXT_PROPERTIES = [
52
- "padding",
53
- "font-family",
54
- "font-size",
55
- "font-style",
56
- "font-weight",
57
- "font-stretch",
58
- "font-variation-settings",
59
- "font-feature-settings",
60
- "line-height",
61
- "letter-spacing",
62
- "word-spacing",
63
- "white-space",
64
- "text-wrap",
65
- "overflow-wrap",
66
- "word-break",
67
- "line-break",
68
- "hyphens",
69
- "text-align",
70
- "text-indent",
71
- "text-transform",
72
- "text-decoration",
73
- "text-decoration-color",
74
- "text-decoration-style",
75
- "text-decoration-thickness",
76
- "text-underline-offset",
77
- "direction",
78
- "writing-mode"
79
- ];
80
- function ghostSource(host) {
81
- const labels = host.querySelectorAll(":scope > a-button-label");
82
- return labels.length === 1 ? labels[0] : host;
83
- }
63
+ const FEEDBACK_MS = 900;
64
+ const COPY_FEEDBACK_TEMPLATE = typeof document === "undefined" ? void 0 : (() => {
65
+ const template = document.createElement("template");
66
+ const style = document.createElement("style");
67
+ style.textContent = `
68
+ .feedback {
69
+ position: fixed;
70
+ margin: 0;
71
+ padding: 0;
72
+ border: 0;
73
+ inset: auto;
74
+ background: none;
75
+ overflow: visible;
76
+ pointer-events: none;
77
+ display: inline-flex;
78
+ align-items: center;
79
+ gap: 4px;
80
+ box-sizing: border-box;
81
+ color: var(--text-2-success);
82
+ font-family: var(--sans-serif);
83
+ font-size: 13px;
84
+ line-height: 16px;
85
+ font-weight: 500;
86
+ white-space: nowrap;
87
+ transform: translate(var(--_feedback-x), calc(-100% - 10px));
88
+ }
89
+ .feedback:not(:popover-open) { display: none; }
90
+ .feedback[data-show] { animation: a-copy-feedback-rise ${FEEDBACK_MS}ms ease-out forwards; }
91
+ @keyframes a-copy-feedback-rise {
92
+ from { opacity: 1; transform: translate(var(--_feedback-x), calc(-100% - 10px)); }
93
+ to { opacity: 0; transform: translate(var(--_feedback-x), calc(-100% - 1.5em)); }
94
+ }
95
+ `;
96
+ const feedback = document.createElement("div");
97
+ feedback.className = "feedback";
98
+ feedback.part.add("feedback");
99
+ feedback.setAttribute("popover", "manual");
100
+ feedback.setAttribute("role", "status");
101
+ const icon = document.createElement("span");
102
+ icon.setAttribute("aria-hidden", "true");
103
+ icon.textContent = "\u2713";
104
+ const label = document.createElement("span");
105
+ label.className = "label";
106
+ feedback.append(icon, label);
107
+ template.content.append(style, feedback);
108
+ return template;
109
+ })();
84
110
  class ACopyElement extends HTMLElementBase {
85
- #ghost;
86
- #ghostTimer;
111
+ #feedback;
112
+ #feedbackLabel;
113
+ #feedbackTimer;
87
114
  connectedCallback() {
88
115
  installCopyDelegation(this.doc);
89
116
  this.addEventListener("copydone", this.#onCopyDone);
90
117
  }
91
118
  /** Run the copy for the activated host. Called from the delegated click /
92
- * menuselect handlers; the ghost (if any) follows on `copydone`. */
119
+ * menuselect handlers; the confirmation follows a successful `copydone`. */
93
120
  activate() {
94
121
  runCopy(this);
95
122
  }
96
123
  #onCopyDone = (e) => {
124
+ const origin = pointerOrigins.get(this);
125
+ pointerOrigins.delete(this);
97
126
  if (!this.hasAttribute("toast")) return;
98
127
  if (!e.detail?.ok) return;
99
128
  const host = this.closest(ANY_HOST);
100
- if (host) this.#showGhost(host);
129
+ if (host) this.#showFeedback(host, origin);
101
130
  };
102
131
  #buildShadow() {
132
+ if (!COPY_FEEDBACK_TEMPLATE) return;
103
133
  const root = this.attachShadow({ mode: "open" });
104
- root.innerHTML = `<style>
105
- .ghost {
106
- position: fixed;
107
- margin: 0;
108
- padding: 0;
109
- border: 0;
110
- inset: auto;
111
- background: none;
112
- overflow: visible;
113
- pointer-events: none;
114
- display: block;
115
- box-sizing: border-box;
116
- font: inherit;
117
- color: inherit;
118
- white-space: normal;
119
- }
120
- .ghost:not(:popover-open) { display: none; }
121
- .ghost[data-show] { animation: a-copy-rise ${GHOST_MS - 50}ms ease-out forwards; }
122
- @keyframes a-copy-rise {
123
- from { opacity: 1; transform: translateY(0); }
124
- to { opacity: 0; transform: translateY(-1.5em); }
125
- }
126
- </style><div class="ghost" part="ghost" popover="manual"></div>`;
127
- this.#ghost = root.querySelector(".ghost");
134
+ root.append(COPY_FEEDBACK_TEMPLATE.content.cloneNode(true));
135
+ this.#feedback = root.querySelector(".feedback");
136
+ this.#feedbackLabel = root.querySelector(".label");
128
137
  }
129
- #showGhost(host) {
130
- if (!this.#ghost) this.#buildShadow();
131
- const ghost = this.#ghost;
132
- if (!ghost || typeof ghost.showPopover !== "function") return;
133
- const source = ghostSource(host);
134
- const text = (source.textContent ?? "").trim();
135
- if (!text) return;
136
- const r = source.getBoundingClientRect();
137
- const style = source.ownerDocument.defaultView?.getComputedStyle(source);
138
- ghost.textContent = text;
139
- if (style) {
140
- for (const property of GHOST_TEXT_PROPERTIES) {
141
- ghost.style.setProperty(property, style.getPropertyValue(property));
142
- }
143
- }
144
- ghost.style.left = `${r.left}px`;
145
- ghost.style.top = `${r.top}px`;
146
- ghost.style.width = `${r.width}px`;
147
- ghost.style.height = `${r.height}px`;
148
- clearTimeout(this.#ghostTimer);
149
- ghost.removeAttribute("data-show");
150
- if (ghost.matches(":popover-open")) {
151
- try {
152
- ghost.hidePopover();
153
- } catch {
154
- }
155
- }
156
- try {
157
- ghost.showPopover();
158
- } catch {
159
- return;
138
+ #showFeedback(host, origin) {
139
+ if (!this.#feedback) this.#buildShadow();
140
+ const feedback = this.#feedback;
141
+ const label = this.#feedbackLabel;
142
+ if (!feedback || !label) return;
143
+ label.textContent = this.getAttribute("copied-label") ?? "Copied";
144
+ if (origin) {
145
+ feedback.style.left = `${origin.x}px`;
146
+ feedback.style.top = `${origin.y}px`;
147
+ feedback.style.setProperty("--_feedback-x", "8px");
148
+ } else {
149
+ const rect = host.getBoundingClientRect();
150
+ const rtl = this.view.getComputedStyle(host).direction === "rtl";
151
+ feedback.style.left = `${rtl ? rect.right - 12 : rect.left + 12}px`;
152
+ feedback.style.top = `${rect.top}px`;
153
+ feedback.style.setProperty("--_feedback-x", rtl ? "-100%" : "0");
160
154
  }
161
- void ghost.offsetWidth;
162
- ghost.setAttribute("data-show", "");
163
- this.#ghostTimer = setTimeout(() => {
164
- ghost.removeAttribute("data-show");
165
- if (ghost.matches(":popover-open")) {
166
- try {
167
- ghost.hidePopover();
168
- } catch {
169
- }
170
- }
171
- }, GHOST_MS);
155
+ clearTimeout(this.#feedbackTimer);
156
+ feedback.removeAttribute("data-show");
157
+ if (feedback.matches(":popover-open")) feedback.hidePopover();
158
+ feedback.showPopover();
159
+ void feedback.offsetWidth;
160
+ feedback.setAttribute("data-show", "");
161
+ this.#feedbackTimer = setTimeout(() => {
162
+ feedback.removeAttribute("data-show");
163
+ if (feedback.matches(":popover-open")) feedback.hidePopover();
164
+ }, FEEDBACK_MS);
172
165
  }
173
166
  disconnectedCallback() {
174
- clearTimeout(this.#ghostTimer);
167
+ clearTimeout(this.#feedbackTimer);
168
+ pointerOrigins.delete(this);
175
169
  this.removeEventListener("copydone", this.#onCopyDone);
176
170
  }
177
171
  }
@@ -1 +1 @@
1
- @layer anta{a-input-time:not(:defined){display:grid;grid-template-columns:minmax(0,1fr);row-gap:4px}a-input-time:not(:defined)>[slot=leading],a-input-time:not(:defined)>[slot=trailing],a-input-time:not(:defined)>[slot=clear],a-input-time:not(:defined)>[slot=hint]{display:none!important}a-input-time:not(:defined)>[slot=label]{display:block;color:var(--input-time-label);font-family:var(--sans-serif);font-size:15px;line-height:20px;font-weight:500}a-input-time[size=small]:not(:defined)>[slot=label]{font-size:13px;line-height:16px}a-input-time[size=large]:not(:defined)>[slot=label]{font-size:17px;line-height:22px}a-input-time:not(:defined):after{content:"\2013\2013:\2013\2013";display:block;min-height:28px;line-height:28px;padding-inline:8px;border-radius:4px;box-shadow:inset 0 0 0 .5px var(--input-time-border);color:var(--input-time-placeholder);font-family:var(--sans-serif);font-size:15px;font-weight:400;font-feature-settings:"ss02","ss05","tnum";font-variation-settings:"wdth" 100,"slnt" 0,"ital" 0;white-space:nowrap}a-input-time[size=small]:not(:defined):after{min-height:24px;line-height:24px;font-size:13px}a-input-time[size=large]:not(:defined):after{min-height:32px;line-height:32px;font-size:17px}@media(forced-colors:active){a-input-time:not(:defined):after{border:1px solid ButtonBorder}}a-input-time[round]:not(:defined):after{border-radius:var(--input-time-round, 999px)}a-input-time{transition:opacity .28s ease-out 40ms}a-input-time:not(:defined){opacity:.5}@media(prefers-reduced-motion:reduce){a-input-time{transition:none}}a-input-time{--input-time-bg: var(--bg-1);--input-time-border: var(--border-2);--input-time-border-hover: var(--border-1);--input-time-text: var(--text-1);--input-time-label: var(--text-3);--input-time-placeholder: var(--text-3);--input-time-adornment: var(--text-3);--input-time-hint: var(--text-3);--input-time-seg-focus-bg: color-mix(in oklch, var(--focus-ring) 20%, transparent);--input-time-seg-focus-text: var(--text-1);width:fit-content;max-width:100%}a-input-time[round]{--input-time-round: attr(round type(<length>), 999px)}a-input-time[size=small] a-icon{--icon-size: 14px}a-input-time[size=large] a-icon{--icon-size: 18px}a-input-time[tone]:not([tone=""]){--input-time-tone-source: attr(tone type(<color>), var(--border-2));--input-time-border: oklch(from var(--input-time-tone-source) .7 calc(c*.8) h);--input-time-border-hover: oklch(from var(--input-time-tone-source) .6 c h);.dark &{--input-time-border: oklch(from var(--input-time-tone-source) .5 calc(c*.8) h);--input-time-border-hover: oklch(from var(--input-time-tone-source) .6 c h)}}a-input-time[status=critical]{--input-time-tone-source: var(--anta-seed-critical);--input-time-bg: var(--bg-2-critical);--input-time-hint: var(--text-2-critical)}a-input-time[status=warning]{--input-time-tone-source: var(--anta-seed-warning);--input-time-bg: var(--bg-2-warning);--input-time-hint: var(--text-2-warning)}a-input-time[status=success]{--input-time-tone-source: var(--anta-seed-success);--input-time-bg: var(--bg-2-success);--input-time-hint: var(--text-2-success)}a-input-time[status=info]{--input-time-tone-source: var(--anta-seed-info);--input-time-bg: var(--bg-2-info);--input-time-hint: var(--text-2-info)}a-input-time[status=brand]{--input-time-tone-source: var(--anta-seed-brand);--input-time-bg: var(--bg-2-brand);--input-time-hint: var(--text-2-brand)}a-input-time[status]{--input-time-border: oklch(from var(--input-time-tone-source) .58 c h);--input-time-border-hover: oklch(from var(--input-time-tone-source) .58 c h)}.dark a-input-time[status]{--input-time-border: oklch(from var(--input-time-tone-source) .52 c h);--input-time-border-hover: oklch(from var(--input-time-tone-source) .52 c h)}a-input-time:disabled{--input-time-bg: #44374b12;--input-time-border: #44374b26;--input-time-border-hover: #44374b26;--input-time-text: var(--text-4);--input-time-label: var(--text-4);--input-time-hint: var(--text-5);cursor:not-allowed}.dark a-input-time:disabled{--input-time-bg: #e4d1ef0d;--input-time-border: #e4d1ef1f;--input-time-border-hover: #e4d1ef1f}.dark a-input-time{--input-time-seg-focus-bg: color-mix(in oklch, var(--focus-ring) 30%, transparent)}}
1
+ @layer anta{a-input-time:not(:defined){display:grid;grid-template-columns:minmax(0,1fr);row-gap:4px}a-input-time:not(:defined)>[slot=leading],a-input-time:not(:defined)>[slot=trailing],a-input-time:not(:defined)>[slot=clear],a-input-time:not(:defined)>[slot=hint]{display:none!important}a-input-time:not(:defined)>[slot=label]{display:block;color:var(--input-time-label);font-family:var(--sans-serif);font-size:var(--input-time-font-size);line-height:var(--input-time-line-height);font-weight:500}a-input-time:not(:defined):after{content:"\2013\2013:\2013\2013";display:block;min-height:var(--input-time-field-height);line-height:var(--input-time-field-height);padding-inline:8px;border-radius:var(--input-time-field-radius);box-shadow:inset 0 0 0 .5px var(--input-time-border);color:var(--input-time-placeholder);font-family:var(--sans-serif);font-size:var(--input-time-font-size);font-weight:400;font-feature-settings:"ss02","ss05","tnum";font-variation-settings:"wdth" 100,"slnt" 0,"ital" 0;white-space:nowrap}@media(forced-colors:active){a-input-time:not(:defined):after{border:1px solid ButtonBorder}}a-input-time{transition:opacity .28s ease-out 40ms}a-input-time:not(:defined){opacity:.5}@media(prefers-reduced-motion:reduce){a-input-time{transition:none}}a-input-time{--input-time-bg: var(--bg-1);--input-time-border: var(--border-2);--input-time-border-hover: var(--border-1);--input-time-text: var(--text-1);--input-time-label: var(--text-3);--input-time-placeholder: var(--text-3);--input-time-adornment: var(--text-3);--input-time-hint: var(--text-3);--input-time-period-color: var(--text-3);--input-time-font-size: 15px;--input-time-line-height: 20px;--input-time-field-height: 28px;--input-time-field-radius: 4px;width:fit-content;max-width:100%}a-input-time:has(>[slot=label])::part(label){display:block}a-input-time:has(>[slot=leading])::part(leading){display:flex;align-items:center;flex-shrink:0;margin-inline-start:7px}a-input-time:has(>[slot=leading])::part(segments){padding-inline-start:4px}a-input-time:has(>[slot=trailing])::part(trailing){display:flex;align-items:center;gap:2px;flex-shrink:0;color:var(--input-time-adornment);font-size:var(--input-time-font-size)}a-input-time:has(>[slot=hint])::part(hint){display:flex}a-input-time[size=small]{--input-time-font-size: 13px;--input-time-line-height: 16px;--input-time-field-height: 24px}a-input-time[size=large]{--input-time-font-size: 17px;--input-time-line-height: 22px;--input-time-field-height: 32px}a-input-time[round]{--input-time-round: attr(round type(<length>), 999px);--input-time-field-radius: var(--input-time-round, 999px)}a-input-time[size=small] a-icon{--icon-size: 14px}a-input-time[size=large] a-icon{--icon-size: 18px}a-input-time[tone]:not([tone=""]){--input-time-tone-source: attr(tone type(<color>), var(--border-2));--input-time-border: oklch(from var(--input-time-tone-source) .7 calc(c*.8) h);--input-time-border-hover: oklch(from var(--input-time-tone-source) .6 c h);.dark &{--input-time-border: oklch(from var(--input-time-tone-source) .5 calc(c*.8) h);--input-time-border-hover: oklch(from var(--input-time-tone-source) .6 c h)}}a-input-time[status=critical]{--input-time-tone-source: var(--anta-seed-critical);--input-time-bg: var(--bg-2-critical);--input-time-hint: var(--text-2-critical)}a-input-time[status=warning]{--input-time-tone-source: var(--anta-seed-warning);--input-time-bg: var(--bg-2-warning);--input-time-hint: var(--text-2-warning)}a-input-time[status=success]{--input-time-tone-source: var(--anta-seed-success);--input-time-bg: var(--bg-2-success);--input-time-hint: var(--text-2-success)}a-input-time[status=info]{--input-time-tone-source: var(--anta-seed-info);--input-time-bg: var(--bg-2-info);--input-time-hint: var(--text-2-info)}a-input-time[status=brand]{--input-time-tone-source: var(--anta-seed-brand);--input-time-bg: var(--bg-2-brand);--input-time-hint: var(--text-2-brand)}a-input-time[status]{--input-time-border: oklch(from var(--input-time-tone-source) .58 c h);--input-time-border-hover: oklch(from var(--input-time-tone-source) .58 c h)}.dark a-input-time[status]{--input-time-border: oklch(from var(--input-time-tone-source) .52 c h);--input-time-border-hover: oklch(from var(--input-time-tone-source) .52 c h)}a-input-time:disabled{--input-time-bg: #44374b12;--input-time-border: #44374b26;--input-time-border-hover: #44374b26;--input-time-text: var(--text-4);--input-time-label: var(--text-4);--input-time-hint: var(--text-5);cursor:not-allowed}.dark a-input-time:disabled{--input-time-bg: #e4d1ef0d;--input-time-border: #e4d1ef1f;--input-time-border-hover: #e4d1ef1f}}