@iris-ui-kit/vue 0.2.28 → 0.2.30

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.
@@ -23,9 +23,8 @@ function getFocusable(root) {
23
23
  (el) => !el.hasAttribute("disabled") && el.tabIndex !== -1
24
24
  );
25
25
  }
26
- function useFocusTrap(options) {
27
- let previouslyFocused = null;
28
- const onKeyDown = (event) => {
26
+ function createFocusTrapKeyHandler(options) {
27
+ return (event) => {
29
28
  if (!options.active.value || event.key !== "Tab") return;
30
29
  const root = options.container.value;
31
30
  if (!root) return;
@@ -43,13 +42,15 @@ function useFocusTrap(options) {
43
42
  event.preventDefault();
44
43
  last.focus();
45
44
  }
46
- } else {
47
- if (active === last || !root.contains(active)) {
48
- event.preventDefault();
49
- first.focus();
50
- }
45
+ } else if (active === last || !root.contains(active)) {
46
+ event.preventDefault();
47
+ first.focus();
51
48
  }
52
49
  };
50
+ }
51
+ function useFocusTrap(options) {
52
+ let previouslyFocused = null;
53
+ const onKeyDown = createFocusTrapKeyHandler(options);
53
54
  const activate = () => {
54
55
  if (typeof document === "undefined") return;
55
56
  previouslyFocused = document.activeElement ?? null;
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/primitives/modal-utils/useFocusTrap.ts","../src/primitives/modal-utils/useBodyScrollLock.ts"],"names":["watch","onScopeDispose"],"mappings":"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","file":"modal-utils.cjs","sourcesContent":["import { onScopeDispose, watch, type Ref } from 'vue'\n\nconst FOCUSABLE_SELECTOR = [\n 'a[href]',\n 'area[href]',\n 'button:not([disabled])',\n 'input:not([disabled]):not([type=\"hidden\"])',\n 'select:not([disabled])',\n 'textarea:not([disabled])',\n '[tabindex]:not([tabindex=\"-1\"])',\n '[contenteditable=\"true\"]',\n 'audio[controls]',\n 'video[controls]',\n 'iframe',\n 'object',\n 'embed',\n].join(',')\n\nfunction getFocusable(root: HTMLElement): HTMLElement[] {\n return Array.from(root.querySelectorAll<HTMLElement>(FOCUSABLE_SELECTOR)).filter(\n (el) => !el.hasAttribute('disabled') && el.tabIndex !== -1,\n )\n}\n\nexport interface UseFocusTrapOptions {\n /** Element whose Tab key cycle is being trapped. */\n container: Ref<HTMLElement | null>\n /** Whether the trap is currently active. */\n active: Ref<boolean>\n /** Element to restore focus to when the trap deactivates. */\n returnFocusTo?: Ref<HTMLElement | null | undefined>\n /** Whether to focus the first focusable element on activation. Default `true`. */\n initialFocus?: boolean\n}\n\n/**\n * Constrain Tab / Shift+Tab focus traversal to descendants of `container`.\n *\n * Behavior on activation:\n * - Records the currently focused element.\n * - If `initialFocus !== false`, focuses the first focusable descendant\n * (or the container itself if there are none).\n *\n * Behavior while active:\n * - Tab on the last focusable element wraps to the first; Shift+Tab on\n * the first wraps to the last.\n *\n * Behavior on deactivation:\n * - Restores focus to `returnFocusTo?.value` if provided, else to the\n * element that was focused when the trap activated.\n */\nexport function useFocusTrap(options: UseFocusTrapOptions): void {\n let previouslyFocused: HTMLElement | null = null\n\n const onKeyDown = (event: KeyboardEvent) => {\n if (!options.active.value || event.key !== 'Tab') return\n const root = options.container.value\n if (!root) return\n const focusables = getFocusable(root)\n if (focusables.length === 0) {\n event.preventDefault()\n root.focus()\n return\n }\n const first = focusables[0]!\n const last = focusables[focusables.length - 1]!\n const active = document.activeElement as HTMLElement | null\n\n if (event.shiftKey) {\n if (active === first || !root.contains(active)) {\n event.preventDefault()\n last.focus()\n }\n } else {\n if (active === last || !root.contains(active)) {\n event.preventDefault()\n first.focus()\n }\n }\n }\n\n const activate = () => {\n if (typeof document === 'undefined') return\n previouslyFocused = (document.activeElement as HTMLElement | null) ?? null\n document.addEventListener('keydown', onKeyDown)\n if (options.initialFocus !== false) {\n requestAnimationFrame(() => {\n const root = options.container.value\n if (!root) return\n const focusables = getFocusable(root)\n ;(focusables[0] ?? root).focus()\n })\n }\n }\n\n const deactivate = () => {\n if (typeof document === 'undefined') return\n document.removeEventListener('keydown', onKeyDown)\n const restore = options.returnFocusTo?.value ?? previouslyFocused\n requestAnimationFrame(() => {\n // The element that had focus when the trap opened may have been\n // unmounted while it was open; focusing a detached node silently drops\n // focus to <body>. Only restore if it is still in the document.\n if (restore && restore.isConnected) restore.focus?.()\n })\n previouslyFocused = null\n }\n\n watch(\n options.active,\n (active, wasActive) => {\n if (active && !wasActive) activate()\n else if (!active && wasActive) deactivate()\n },\n { immediate: true, flush: 'post' },\n )\n\n onScopeDispose(() => {\n if (typeof document !== 'undefined') {\n document.removeEventListener('keydown', onKeyDown)\n }\n })\n}\n","import { onScopeDispose, watch, type Ref } from 'vue'\n\nlet lockCount = 0\nlet savedOverflow: string | null = null\nlet savedPaddingRight: string | null = null\n// What we actually wrote, so unlock can detect a host mutation made while\n// locked and avoid clobbering it.\nlet appliedOverflow: string | null = null\nlet appliedPaddingRight: string | null = null\n\nfunction lock() {\n if (typeof document === 'undefined') return\n lockCount += 1\n if (lockCount > 1) return\n const body = document.body\n const scrollbarWidth = window.innerWidth - document.documentElement.clientWidth\n savedOverflow = body.style.overflow\n savedPaddingRight = body.style.paddingRight\n body.style.overflow = 'hidden'\n appliedOverflow = 'hidden'\n if (scrollbarWidth > 0) {\n const currentPadding = parseFloat(getComputedStyle(body).paddingRight || '0')\n appliedPaddingRight = `${currentPadding + scrollbarWidth}px`\n body.style.paddingRight = appliedPaddingRight\n } else {\n appliedPaddingRight = null\n }\n}\n\nfunction unlock() {\n if (typeof document === 'undefined') return\n lockCount = Math.max(0, lockCount - 1)\n if (lockCount > 0) return\n const body = document.body\n // Only restore if our locked value is still in place; if a host changed body\n // overflow / padding-right while locked, respect that rather than clobber it.\n if (body.style.overflow === appliedOverflow) {\n body.style.overflow = savedOverflow ?? ''\n }\n if (appliedPaddingRight !== null && body.style.paddingRight === appliedPaddingRight) {\n body.style.paddingRight = savedPaddingRight ?? ''\n }\n savedOverflow = null\n savedPaddingRight = null\n appliedOverflow = null\n appliedPaddingRight = null\n}\n\n/**\n * Lock the document body's scroll while `active` is true. Reference-counted\n * so multiple stacked Dialogs cooperate. Restores prior `overflow` and\n * `padding-right` (to compensate for the scrollbar gap) when the last lock\n * releases. SSR-safe.\n */\nexport function useBodyScrollLock(active: Ref<boolean>): void {\n let isLockedByThis = false\n\n watch(\n active,\n (value) => {\n if (value && !isLockedByThis) {\n lock()\n isLockedByThis = true\n } else if (!value && isLockedByThis) {\n unlock()\n isLockedByThis = false\n }\n },\n { immediate: true, flush: 'post' },\n )\n\n onScopeDispose(() => {\n if (isLockedByThis) {\n unlock()\n isLockedByThis = false\n }\n })\n}\n\n/** Test-only: read the current lock count. */\nexport function __getBodyScrollLockCount(): number {\n return lockCount\n}\n\n/** Test-only: hard-reset the module-level lock state. */\nexport function __resetBodyScrollLock(): void {\n lockCount = 0\n savedOverflow = null\n savedPaddingRight = null\n appliedOverflow = null\n appliedPaddingRight = null\n if (typeof document !== 'undefined') {\n document.body.style.overflow = ''\n document.body.style.paddingRight = ''\n }\n}\n"]}
1
+ {"version":3,"sources":["../src/primitives/modal-utils/useFocusTrap.ts","../src/primitives/modal-utils/useBodyScrollLock.ts"],"names":["watch","onScopeDispose"],"mappings":"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","file":"modal-utils.cjs","sourcesContent":["import { onScopeDispose, watch, type Ref } from 'vue'\n\nconst FOCUSABLE_SELECTOR = [\n 'a[href]',\n 'area[href]',\n 'button:not([disabled])',\n 'input:not([disabled]):not([type=\"hidden\"])',\n 'select:not([disabled])',\n 'textarea:not([disabled])',\n '[tabindex]:not([tabindex=\"-1\"])',\n '[contenteditable=\"true\"]',\n 'audio[controls]',\n 'video[controls]',\n 'iframe',\n 'object',\n 'embed',\n].join(',')\n\nfunction getFocusable(root: HTMLElement): HTMLElement[] {\n return Array.from(root.querySelectorAll<HTMLElement>(FOCUSABLE_SELECTOR)).filter(\n (el) => !el.hasAttribute('disabled') && el.tabIndex !== -1,\n )\n}\n\nexport interface UseFocusTrapOptions {\n /** Element whose Tab key cycle is being trapped. */\n container: Ref<HTMLElement | null>\n /** Whether the trap is currently active. */\n active: Ref<boolean>\n /** Element to restore focus to when the trap deactivates. */\n returnFocusTo?: Ref<HTMLElement | null | undefined>\n /** Whether to focus the first focusable element on activation. Default `true`. */\n initialFocus?: boolean\n}\n\nfunction createFocusTrapKeyHandler(options: UseFocusTrapOptions): (event: KeyboardEvent) => void {\n return (event: KeyboardEvent): void => {\n if (!options.active.value || event.key !== 'Tab') return\n const root = options.container.value\n if (!root) return\n const focusables = getFocusable(root)\n if (focusables.length === 0) {\n event.preventDefault()\n root.focus()\n return\n }\n const first = focusables[0]!\n const last = focusables[focusables.length - 1]!\n const active = document.activeElement as HTMLElement | null\n\n if (event.shiftKey) {\n if (active === first || !root.contains(active)) {\n event.preventDefault()\n last.focus()\n }\n } else if (active === last || !root.contains(active)) {\n event.preventDefault()\n first.focus()\n }\n }\n}\n\n/**\n * Constrain Tab / Shift+Tab focus traversal to descendants of `container`.\n *\n * Behavior on activation:\n * - Records the currently focused element.\n * - If `initialFocus !== false`, focuses the first focusable descendant\n * (or the container itself if there are none).\n *\n * Behavior while active:\n * - Tab on the last focusable element wraps to the first; Shift+Tab on\n * the first wraps to the last.\n *\n * Behavior on deactivation:\n * - Restores focus to `returnFocusTo?.value` if provided, else to the\n * element that was focused when the trap activated.\n */\nexport function useFocusTrap(options: UseFocusTrapOptions): void {\n let previouslyFocused: HTMLElement | null = null\n\n const onKeyDown = createFocusTrapKeyHandler(options)\n\n const activate = () => {\n if (typeof document === 'undefined') return\n previouslyFocused = (document.activeElement as HTMLElement | null) ?? null\n document.addEventListener('keydown', onKeyDown)\n if (options.initialFocus !== false) {\n requestAnimationFrame(() => {\n const root = options.container.value\n if (!root) return\n const focusables = getFocusable(root)\n ;(focusables[0] ?? root).focus()\n })\n }\n }\n\n const deactivate = () => {\n if (typeof document === 'undefined') return\n document.removeEventListener('keydown', onKeyDown)\n const restore = options.returnFocusTo?.value ?? previouslyFocused\n requestAnimationFrame(() => {\n // The element that had focus when the trap opened may have been\n // unmounted while it was open; focusing a detached node silently drops\n // focus to <body>. Only restore if it is still in the document.\n if (restore && restore.isConnected) restore.focus?.()\n })\n previouslyFocused = null\n }\n\n watch(\n options.active,\n (active, wasActive) => {\n if (active && !wasActive) activate()\n else if (!active && wasActive) deactivate()\n },\n { immediate: true, flush: 'post' },\n )\n\n onScopeDispose(() => {\n if (typeof document !== 'undefined') {\n document.removeEventListener('keydown', onKeyDown)\n }\n })\n}\n","import { onScopeDispose, watch, type Ref } from 'vue'\n\nlet lockCount = 0\nlet savedOverflow: string | null = null\nlet savedPaddingRight: string | null = null\n// What we actually wrote, so unlock can detect a host mutation made while\n// locked and avoid clobbering it.\nlet appliedOverflow: string | null = null\nlet appliedPaddingRight: string | null = null\n\nfunction lock() {\n if (typeof document === 'undefined') return\n lockCount += 1\n if (lockCount > 1) return\n const body = document.body\n const scrollbarWidth = window.innerWidth - document.documentElement.clientWidth\n savedOverflow = body.style.overflow\n savedPaddingRight = body.style.paddingRight\n body.style.overflow = 'hidden'\n appliedOverflow = 'hidden'\n if (scrollbarWidth > 0) {\n const currentPadding = parseFloat(getComputedStyle(body).paddingRight || '0')\n appliedPaddingRight = `${currentPadding + scrollbarWidth}px`\n body.style.paddingRight = appliedPaddingRight\n } else {\n appliedPaddingRight = null\n }\n}\n\nfunction unlock() {\n if (typeof document === 'undefined') return\n lockCount = Math.max(0, lockCount - 1)\n if (lockCount > 0) return\n const body = document.body\n // Only restore if our locked value is still in place; if a host changed body\n // overflow / padding-right while locked, respect that rather than clobber it.\n if (body.style.overflow === appliedOverflow) {\n body.style.overflow = savedOverflow ?? ''\n }\n if (appliedPaddingRight !== null && body.style.paddingRight === appliedPaddingRight) {\n body.style.paddingRight = savedPaddingRight ?? ''\n }\n savedOverflow = null\n savedPaddingRight = null\n appliedOverflow = null\n appliedPaddingRight = null\n}\n\n/**\n * Lock the document body's scroll while `active` is true. Reference-counted\n * so multiple stacked Dialogs cooperate. Restores prior `overflow` and\n * `padding-right` (to compensate for the scrollbar gap) when the last lock\n * releases. SSR-safe.\n */\nexport function useBodyScrollLock(active: Ref<boolean>): void {\n let isLockedByThis = false\n\n watch(\n active,\n (value) => {\n if (value && !isLockedByThis) {\n lock()\n isLockedByThis = true\n } else if (!value && isLockedByThis) {\n unlock()\n isLockedByThis = false\n }\n },\n { immediate: true, flush: 'post' },\n )\n\n onScopeDispose(() => {\n if (isLockedByThis) {\n unlock()\n isLockedByThis = false\n }\n })\n}\n\n/** Test-only: read the current lock count. */\nexport function __getBodyScrollLockCount(): number {\n return lockCount\n}\n\n/** Test-only: hard-reset the module-level lock state. */\nexport function __resetBodyScrollLock(): void {\n lockCount = 0\n savedOverflow = null\n savedPaddingRight = null\n appliedOverflow = null\n appliedPaddingRight = null\n if (typeof document !== 'undefined') {\n document.body.style.overflow = ''\n document.body.style.paddingRight = ''\n }\n}\n"]}
@@ -1,3 +1,3 @@
1
- export { __getBodyScrollLockCount, __resetBodyScrollLock, useBodyScrollLock, useFocusTrap } from './chunk-XCNCIG2I.js';
1
+ export { __getBodyScrollLockCount, __resetBodyScrollLock, useBodyScrollLock, useFocusTrap } from './chunk-LQ2YAOYR.js';
2
2
  //# sourceMappingURL=modal-utils.js.map
3
3
  //# sourceMappingURL=modal-utils.js.map
@@ -154,11 +154,11 @@ var IrisInput = vue.defineComponent({
154
154
  display: "inline-flex",
155
155
  alignItems: "center",
156
156
  gap: "var(--iris-gap-sm)",
157
- background: "var(--iris-background)",
157
+ background: props.readonly ? "var(--iris-surface)" : "var(--iris-background)",
158
158
  color: "var(--iris-foreground)",
159
159
  border: `1px solid ${borderColor}`,
160
160
  borderRadius: "var(--iris-radius-md)",
161
- cursor: props.disabled ? "not-allowed" : "text",
161
+ cursor: props.disabled ? "not-allowed" : props.readonly ? "default" : "text",
162
162
  opacity: props.disabled ? "0.6" : "1",
163
163
  transition: "border-color 120ms ease, box-shadow 120ms ease",
164
164
  boxShadow,
@@ -198,7 +198,7 @@ var IrisInput = vue.defineComponent({
198
198
  ...attrs,
199
199
  "data-iris-input": "",
200
200
  "data-iris-input-size": props.size,
201
- "data-state": props.invalid ? "invalid" : focused.value ? "focused" : "idle",
201
+ "data-state": props.invalid ? "invalid" : focused.value ? "focused" : props.readonly ? "readonly" : "idle",
202
202
  style: {
203
203
  ...wrapperStyle.value,
204
204
  ...attrs.style ?? {}
@@ -657,15 +657,18 @@ function findFirstElement(children) {
657
657
  var SIZE_STYLES = {
658
658
  sm: {
659
659
  padding: "var(--iris-padding-sm) var(--iris-padding-md)",
660
- fontSize: "var(--iris-font-size-xs, 12px)"
660
+ fontSize: "var(--iris-font-size-xs, 12px)",
661
+ minHeight: "var(--iris-control-height-sm, 28px)"
661
662
  },
662
663
  md: {
663
664
  padding: "var(--iris-padding-sm) var(--iris-padding-lg)",
664
- fontSize: "var(--iris-font-size-md, 14px)"
665
+ fontSize: "var(--iris-font-size-md, 14px)",
666
+ minHeight: "var(--iris-control-height-md, 34px)"
665
667
  },
666
668
  lg: {
667
669
  padding: "var(--iris-padding-md) var(--iris-padding-lg)",
668
- fontSize: "var(--iris-font-size-lg, 16px)"
670
+ fontSize: "var(--iris-font-size-lg, 16px)",
671
+ minHeight: "var(--iris-control-height-lg, 40px)"
669
672
  }
670
673
  };
671
674
  var VARIANT_STYLES = {
@@ -700,6 +703,7 @@ function buildInlineStyle(variant, size) {
700
703
  const base = { ...SIZE_STYLES[size], ...VARIANT_STYLES[variant] };
701
704
  if (variant === "link") {
702
705
  base.padding = "0";
706
+ delete base.minHeight;
703
707
  }
704
708
  return base;
705
709
  }