@antadesign/anta 0.3.5 → 0.3.6

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.
@@ -52,6 +52,9 @@ export declare class ATooltipElement extends HTMLElementBase {
52
52
  private fading;
53
53
  private fadeTimer?;
54
54
  private docMoveBound;
55
+ /** Active only while shown: re-runs the empty gate when the slotted content
56
+ * changes under a live bubble. See observeContent(). */
57
+ private contentObserver?;
55
58
  constructor();
56
59
  connectedCallback(): void;
57
60
  disconnectedCallback(): void;
@@ -76,6 +79,20 @@ export declare class ATooltipElement extends HTMLElementBase {
76
79
  * (so formatting whitespace / an empty conditional doesn't open a blank bubble).
77
80
  * Re-checked on every show(), so a tooltip populated later self-corrects. */
78
81
  private isEmpty;
82
+ /** While shown, watch the slotted content so a bubble whose content is
83
+ * cleared out from under it — a reactive re-render dropping the text /
84
+ * children under one persistent anchor — self-hides. The mirror of
85
+ * isEmpty()'s "populated later self-corrects": the show-time gate can't fire
86
+ * again on its own once open, so this drives the reverse.
87
+ *
88
+ * A MutationObserver, not `slotchange`, because reactive renderers update
89
+ * text in place — React sets an existing text node's nodeValue rather than
90
+ * replacing the node — which changes no assigned-node set and so fires no
91
+ * `slotchange`; childList + characterData + subtree catches both that and
92
+ * node removal. Observing our own light-DOM children is a READ (like the
93
+ * truncation measurements), so it stays within the no-host-mutation rule.
94
+ * Runs only while shown — attached here, disconnected by hide() / cleanup(). */
95
+ private observeContent;
79
96
  private positionFrame?;
80
97
  private pendingPosition?;
81
98
  private schedulePosition;
@@ -85,6 +85,9 @@ class ATooltipElement extends HTMLElementBase {
85
85
  fading = false;
86
86
  fadeTimer;
87
87
  docMoveBound = false;
88
+ /** Active only while shown: re-runs the empty gate when the slotted content
89
+ * changes under a live bubble. See observeContent(). */
90
+ contentObserver;
88
91
  constructor() {
89
92
  super();
90
93
  const shadow = this.attachShadow({ mode: "open" });
@@ -259,6 +262,28 @@ class ATooltipElement extends HTMLElementBase {
259
262
  isEmpty() {
260
263
  return this.children.length === 0 && (this.textContent ?? "").trim() === "";
261
264
  }
265
+ /** While shown, watch the slotted content so a bubble whose content is
266
+ * cleared out from under it — a reactive re-render dropping the text /
267
+ * children under one persistent anchor — self-hides. The mirror of
268
+ * isEmpty()'s "populated later self-corrects": the show-time gate can't fire
269
+ * again on its own once open, so this drives the reverse.
270
+ *
271
+ * A MutationObserver, not `slotchange`, because reactive renderers update
272
+ * text in place — React sets an existing text node's nodeValue rather than
273
+ * replacing the node — which changes no assigned-node set and so fires no
274
+ * `slotchange`; childList + characterData + subtree catches both that and
275
+ * node removal. Observing our own light-DOM children is a READ (like the
276
+ * truncation measurements), so it stays within the no-host-mutation rule.
277
+ * Runs only while shown — attached here, disconnected by hide() / cleanup(). */
278
+ observeContent() {
279
+ if (typeof MutationObserver === "undefined") return;
280
+ if (!this.contentObserver) {
281
+ this.contentObserver = new MutationObserver(() => {
282
+ if (this.shown && this.isEmpty()) this.hide();
283
+ });
284
+ }
285
+ this.contentObserver.observe(this, { childList: true, characterData: true, subtree: true });
286
+ }
262
287
  // --- positioning (sets only the shadow container's own transform) ---
263
288
  // Single pending position frame: a burst of mousemoves within one frame
264
289
  // coalesces to ONE layout read + transform write, using the LATEST geometry
@@ -353,6 +378,7 @@ class ATooltipElement extends HTMLElementBase {
353
378
  this.doc.addEventListener("mousemove", this.onDocMove);
354
379
  this.docMoveBound = true;
355
380
  }
381
+ this.observeContent();
356
382
  }
357
383
  this.position(e);
358
384
  };
@@ -361,6 +387,7 @@ class ATooltipElement extends HTMLElementBase {
361
387
  if (!this.shown) return;
362
388
  this.shown = false;
363
389
  this.touchOpen = false;
390
+ this.contentObserver?.disconnect();
364
391
  this.container.hidePopover();
365
392
  this.fading = true;
366
393
  if (this.fadeTimer !== void 0) clearTimeout(this.fadeTimer);
@@ -391,6 +418,7 @@ class ATooltipElement extends HTMLElementBase {
391
418
  * calls it. */
392
419
  cleanup() {
393
420
  this.cancelHide();
421
+ this.contentObserver?.disconnect();
394
422
  if (this.shown) {
395
423
  this.shown = false;
396
424
  this.touchOpen = false;
@@ -32,5 +32,6 @@ export { AMenuGroupElement, register_a_menu_group } from './a-menu-group';
32
32
  export { ATabElement, register_a_tab } from './a-tab';
33
33
  export { ATabsElement, register_a_tabs } from './a-tabs';
34
34
  export { ATabPanelElement, register_a_tabpanel } from './a-tabpanel';
35
+ export { ADialogElement, register_a_dialog } from './a-dialog';
35
36
  import './a-title.css';
36
37
  import './a-tag.css';
@@ -17,12 +17,14 @@ import { AMenuGroupElement, register_a_menu_group } from "./a-menu-group";
17
17
  import { ATabElement, register_a_tab } from "./a-tab";
18
18
  import { ATabsElement, register_a_tabs } from "./a-tabs";
19
19
  import { ATabPanelElement, register_a_tabpanel } from "./a-tabpanel";
20
+ import { ADialogElement, register_a_dialog } from "./a-dialog";
20
21
  import "./a-title.css";
21
22
  import "./a-tag.css";
22
23
  export {
23
24
  AButtonElement,
24
25
  ACalendarElement,
25
26
  ACheckboxElement,
27
+ ADialogElement,
26
28
  AExpanderElement,
27
29
  AIconElement,
28
30
  AInputElement,
@@ -42,6 +44,7 @@ export {
42
44
  register_a_button,
43
45
  register_a_calendar,
44
46
  register_a_checkbox,
47
+ register_a_dialog,
45
48
  register_a_expander,
46
49
  register_a_icon,
47
50
  register_a_input,
@@ -291,6 +291,51 @@ export interface AExpanderAttributes extends BaseAttributes {
291
291
  prev: 'open' | 'closed';
292
292
  }>) => void;
293
293
  }
294
+ /**
295
+ * Attributes for the `<a-dialog>` custom element — a modal dialog / edge drawer
296
+ * built on a native `<dialog>` in shadow DOM (top layer, focus trap, backdrop,
297
+ * Esc from the platform). Slots (light-DOM children): `header`, `footer`,
298
+ * `close` (the close button), and the default slot for the body. The element
299
+ * exposes `::part(dialog | header | body | footer | close)`. Low-level
300
+ * attributes; for the typed JSX wrapper use `Dialog` from `@antadesign/anta`.
301
+ */
302
+ export interface ADialogAttributes extends BaseAttributes {
303
+ /** Controlled open state (`'open'` / `'closed'`). Present → controlled: the
304
+ * attribute is the source of truth, user dismiss only dispatches the
305
+ * cancelable `statechange` event, and the consumer answers by updating it.
306
+ * Absent → uncontrolled (use `default-state`). See STATEFUL-COMPONENTS.md. */
307
+ state?: 'open' | 'closed';
308
+ /** Initial open state for the uncontrolled mode (`'open'` / `'closed'`); read
309
+ * once when the element connects. */
310
+ 'default-state'?: 'open' | 'closed';
311
+ /** Placement. `center` (default, omit) is a centered modal; `left` / `right` /
312
+ * `top` / `bottom` turn it into an edge drawer; `fullscreen` fills the whole
313
+ * viewport (no edge gap, no radius). */
314
+ position?: 'center' | 'left' | 'right' | 'top' | 'bottom' | 'fullscreen';
315
+ /** Corner radius. A side keyword (`top` / `right` / `bottom` / `left`) rounds
316
+ * only that edge's two corners at `--dialog-radius`; a length (`round="20px"`)
317
+ * or full `border-radius` shorthand rounds all corners at that value; bare
318
+ * `round` rounds all corners at `--dialog-radius`. Omit for the position
319
+ * default (center rounded, drawers / fullscreen square). */
320
+ round?: boolean | number | 'top' | 'right' | 'bottom' | 'left' | (string & {});
321
+ /** Disable light dismiss — Esc + backdrop click no longer close the dialog (it
322
+ * closes only via the close button or programmatically). For alert / confirm
323
+ * dialogs. Presence-based (`''` on, omit off). */
324
+ persistent?: boolean | '';
325
+ /** Uncontrolled trigger name. Any element with `data-dialog-open="{name}"`
326
+ * opens this dialog and `data-dialog-close="{name}"` closes it, via a document
327
+ * click listener. Ignored in controlled mode. */
328
+ name?: string;
329
+ /** Fires before the open state changes — the element dispatches a `cancelable`
330
+ * `statechange` `CustomEvent` whose `detail` is `{ next, prev }` in the
331
+ * `'open'|'closed'` vocabulary. Uncontrolled, `preventDefault()` vetoes the
332
+ * transition. All-lowercase so both renderers bind it (React 19 keeps the case
333
+ * after `on`; Preact lowercases). */
334
+ onstatechange?: (e: CustomEvent<{
335
+ next: 'open' | 'closed';
336
+ prev: 'open' | 'closed';
337
+ }>) => void;
338
+ }
294
339
  /**
295
340
  * Attributes for the `<a-icon>` custom element. `shape` is typed as
296
341
  * `IconShape` (`keyof IconShapes`); the `IconShapes` interface is
package/dist/index.d.ts CHANGED
@@ -51,6 +51,8 @@ export { InputDate } from './components/InputDate';
51
51
  export type { InputDateProps, InputDateChangeAttrs } from './components/InputDate';
52
52
  export { InputTime } from './components/InputTime';
53
53
  export type { InputTimeProps, InputTimeChangeAttrs } from './components/InputTime';
54
+ export { InputAutocomplete } from './components/InputAutocomplete';
55
+ export type { InputAutocompleteProps } from './components/InputAutocomplete';
54
56
  export { buildMonth, getWeekdays, firstDayOfWeek, clampDate, isOutOfRange, parseISODate, parseDateInput, formatDateInput, dateFormatPattern, parseTimeInput, parseDateTimeInput, formatDateTimeInput, dateTimeFormatPattern, usesHour12, } from './calendar-core';
55
57
  export type { CalendarDay, CalendarWeekday, CalendarMonth, BuildMonthOptions, ParseDateOptions, } from './calendar-core';
56
58
  export { RadioGroup } from './components/RadioGroup';
@@ -63,6 +65,8 @@ export { Tabs } from './components/Tabs';
63
65
  export type { TabsProps, TabOption, TabsChangeAttrs } from './components/Tabs';
64
66
  export { TabPanel } from './components/TabPanel';
65
67
  export type { TabPanelProps } from './components/TabPanel';
68
+ export { Dialog } from './components/Dialog';
69
+ export type { DialogProps } from './components/Dialog';
66
70
  export type { BaseProps, BaseAttributes } from './general_types';
67
71
  export { configure } from './jsx-runtime';
68
72
  export type { AntaIntrinsicElements } from './jsx-runtime';
package/dist/index.js CHANGED
@@ -16,6 +16,7 @@ import { Input } from "./components/Input";
16
16
  import { Calendar } from "./components/Calendar";
17
17
  import { InputDate } from "./components/InputDate";
18
18
  import { InputTime } from "./components/InputTime";
19
+ import { InputAutocomplete } from "./components/InputAutocomplete";
19
20
  import {
20
21
  buildMonth,
21
22
  getWeekdays,
@@ -37,16 +38,19 @@ import { Select, optionsWithSelection } from "./components/Select";
37
38
  import { SelectFaceted } from "./components/SelectFaceted";
38
39
  import { Tabs } from "./components/Tabs";
39
40
  import { TabPanel } from "./components/TabPanel";
41
+ import { Dialog } from "./components/Dialog";
40
42
  import { configure } from "./jsx-runtime";
41
43
  export {
42
44
  Button,
43
45
  Calendar,
44
46
  Checkbox,
47
+ Dialog,
45
48
  Expander,
46
49
  ICON_SHAPES,
47
50
  ICON_SYNONYMS,
48
51
  Icon,
49
52
  Input,
53
+ InputAutocomplete,
50
54
  InputDate,
51
55
  InputTime,
52
56
  Menu,
@@ -41,7 +41,7 @@ export declare function useMemo<T>(factory: () => T, deps: unknown[]): T;
41
41
  export declare function jsx(type: ComponentType, props: Record<string, unknown> | null, key?: string | number): unknown;
42
42
  export declare function jsxs(type: ComponentType, props: Record<string, unknown> | null, key?: string | number): unknown;
43
43
  export { _Fragment as Fragment };
44
- import type { AProgressAttributes, ATextAttributes, ATitleAttributes, ATagAttributes, AExpanderAttributes, AIconAttributes, AButtonAttributes, ACheckboxAttributes, ATooltipAttributes, AInputAttributes, AInputTimeAttributes, ACalendarAttributes, ARadioAttributes, ARadioGroupAttributes, AMenuAttributes, AMenuItemAttributes, AMenuGroupAttributes, ATabsAttributes, ATabAttributes, ATabpanelAttributes, BaseAttributes } from './general_types';
44
+ import type { AProgressAttributes, ATextAttributes, ATitleAttributes, ATagAttributes, AExpanderAttributes, AIconAttributes, AButtonAttributes, ACheckboxAttributes, ATooltipAttributes, AInputAttributes, AInputTimeAttributes, ACalendarAttributes, ARadioAttributes, ARadioGroupAttributes, AMenuAttributes, AMenuItemAttributes, AMenuGroupAttributes, ATabsAttributes, ATabAttributes, ATabpanelAttributes, ADialogAttributes, BaseAttributes } from './general_types';
45
45
  export declare namespace JSX {
46
46
  interface IntrinsicElements extends React.JSX.IntrinsicElements, AntaIntrinsicElements {
47
47
  }
@@ -91,4 +91,5 @@ export interface AntaIntrinsicElements {
91
91
  'a-tab': ATabAttributes;
92
92
  'a-tab-label': BaseAttributes;
93
93
  'a-tabpanel': ATabpanelAttributes;
94
+ 'a-dialog': ADialogAttributes;
94
95
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@antadesign/anta",
3
- "version": "0.3.5",
3
+ "version": "0.3.6",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",