@salmexio/ui 1.2.0 → 1.3.0
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/dist/feedback/Alert/Alert.svelte +4 -1
- package/dist/feedback/Alert/Alert.svelte.d.ts +1 -0
- package/dist/feedback/Alert/Alert.svelte.d.ts.map +1 -1
- package/dist/feedback/Spinner/Spinner.svelte +4 -1
- package/dist/feedback/Spinner/Spinner.svelte.d.ts +1 -0
- package/dist/feedback/Spinner/Spinner.svelte.d.ts.map +1 -1
- package/dist/forms/DatePicker/DatePicker.svelte +725 -0
- package/dist/forms/DatePicker/DatePicker.svelte.d.ts +48 -0
- package/dist/forms/DatePicker/DatePicker.svelte.d.ts.map +1 -0
- package/dist/forms/DatePicker/index.d.ts +2 -0
- package/dist/forms/DatePicker/index.d.ts.map +1 -0
- package/dist/forms/DatePicker/index.js +1 -0
- package/dist/forms/FormField/FormField.svelte +173 -0
- package/dist/forms/FormField/FormField.svelte.d.ts +46 -0
- package/dist/forms/FormField/FormField.svelte.d.ts.map +1 -0
- package/dist/forms/FormField/index.d.ts +2 -0
- package/dist/forms/FormField/index.d.ts.map +1 -0
- package/dist/forms/FormField/index.js +1 -0
- package/dist/forms/MultiSelect/MultiSelect.svelte +820 -0
- package/dist/forms/MultiSelect/MultiSelect.svelte.d.ts +69 -0
- package/dist/forms/MultiSelect/MultiSelect.svelte.d.ts.map +1 -0
- package/dist/forms/MultiSelect/index.d.ts +3 -0
- package/dist/forms/MultiSelect/index.d.ts.map +1 -0
- package/dist/forms/MultiSelect/index.js +1 -0
- package/dist/forms/PhoneInput/PhoneInput.svelte +591 -0
- package/dist/forms/PhoneInput/PhoneInput.svelte.d.ts +57 -0
- package/dist/forms/PhoneInput/PhoneInput.svelte.d.ts.map +1 -0
- package/dist/forms/PhoneInput/index.d.ts +4 -0
- package/dist/forms/PhoneInput/index.d.ts.map +1 -0
- package/dist/forms/PhoneInput/index.js +2 -0
- package/dist/forms/RadioGroup/RadioGroup.svelte +417 -0
- package/dist/forms/RadioGroup/RadioGroup.svelte.d.ts +62 -0
- package/dist/forms/RadioGroup/RadioGroup.svelte.d.ts.map +1 -0
- package/dist/forms/RadioGroup/index.d.ts +3 -0
- package/dist/forms/RadioGroup/index.d.ts.map +1 -0
- package/dist/forms/RadioGroup/index.js +1 -0
- package/dist/forms/SearchInput/SearchInput.svelte +788 -0
- package/dist/forms/SearchInput/SearchInput.svelte.d.ts +79 -0
- package/dist/forms/SearchInput/SearchInput.svelte.d.ts.map +1 -0
- package/dist/forms/SearchInput/index.d.ts +3 -0
- package/dist/forms/SearchInput/index.d.ts.map +1 -0
- package/dist/forms/SearchInput/index.js +1 -0
- package/dist/forms/Select/Select.svelte +14 -8
- package/dist/forms/Select/Select.svelte.d.ts +2 -0
- package/dist/forms/Select/Select.svelte.d.ts.map +1 -1
- package/dist/forms/TextInput/TextInput.svelte +38 -16
- package/dist/forms/TextInput/TextInput.svelte.d.ts +6 -0
- package/dist/forms/TextInput/TextInput.svelte.d.ts.map +1 -1
- package/dist/forms/Textarea/Textarea.svelte +7 -1
- package/dist/forms/Textarea/Textarea.svelte.d.ts +2 -0
- package/dist/forms/Textarea/Textarea.svelte.d.ts.map +1 -1
- package/dist/forms/TimePicker/TimePicker.svelte +417 -0
- package/dist/forms/TimePicker/TimePicker.svelte.d.ts +53 -0
- package/dist/forms/TimePicker/TimePicker.svelte.d.ts.map +1 -0
- package/dist/forms/TimePicker/index.d.ts +2 -0
- package/dist/forms/TimePicker/index.d.ts.map +1 -0
- package/dist/forms/TimePicker/index.js +1 -0
- package/dist/forms/index.d.ts +12 -0
- package/dist/forms/index.d.ts.map +1 -1
- package/dist/forms/index.js +8 -0
- package/dist/layout/Container/Container.svelte +3 -0
- package/dist/layout/Container/Container.svelte.d.ts +1 -0
- package/dist/layout/Container/Container.svelte.d.ts.map +1 -1
- package/dist/primitives/Badge/Badge.svelte +5 -1
- package/dist/primitives/Badge/Badge.svelte.d.ts +1 -0
- package/dist/primitives/Badge/Badge.svelte.d.ts.map +1 -1
- package/dist/primitives/Tooltip/Tooltip.svelte +30 -0
- package/dist/primitives/Tooltip/Tooltip.svelte.d.ts.map +1 -1
- package/dist/utils/accessibility.d.ts +16 -0
- package/dist/utils/accessibility.d.ts.map +1 -0
- package/dist/utils/accessibility.js +80 -0
- package/dist/utils/index.d.ts +2 -1
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +2 -1
- package/dist/utils/keyboard.d.ts +6 -0
- package/dist/utils/keyboard.d.ts.map +1 -1
- package/dist/utils/keyboard.js +15 -9
- package/package.json +21 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"accessibility.d.ts","sourceRoot":"","sources":["../../src/utils/accessibility.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAcH,kDAAkD;AAClD,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,WAAW,GAAG,OAAO,CAe3D;AAED,mEAAmE;AACnE,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,WAAW,GAAG,WAAW,EAAE,CAI1E;AAED;;;GAGG;AACH,wBAAgB,QAAQ,CACvB,OAAO,EAAE,MAAM,EACf,QAAQ,GAAE,QAAQ,GAAG,WAAsB,GACzC,IAAI,CAgCN;AAED,gDAAgD;AAChD,wBAAgB,oBAAoB,IAAI,OAAO,CAG9C"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Accessibility utilities for WCAG 2.1 AA compliance.
|
|
3
|
+
* Focus management, screen reader announcements, media query helpers.
|
|
4
|
+
*/
|
|
5
|
+
const FOCUSABLE_SELECTORS = [
|
|
6
|
+
'a[href]:not([tabindex="-1"])',
|
|
7
|
+
'button:not([disabled]):not([tabindex="-1"])',
|
|
8
|
+
'input:not([disabled]):not([tabindex="-1"]):not([type="hidden"])',
|
|
9
|
+
'select:not([disabled]):not([tabindex="-1"])',
|
|
10
|
+
'textarea:not([disabled]):not([tabindex="-1"])',
|
|
11
|
+
'[tabindex]:not([tabindex="-1"])',
|
|
12
|
+
'[contenteditable]:not([tabindex="-1"])',
|
|
13
|
+
];
|
|
14
|
+
const FOCUSABLE_SELECTOR = FOCUSABLE_SELECTORS.join(', ');
|
|
15
|
+
/** Check whether an element can receive focus. */
|
|
16
|
+
export function isElementFocusable(el) {
|
|
17
|
+
if (el.hasAttribute('disabled') || el.disabled)
|
|
18
|
+
return false;
|
|
19
|
+
if (el.getAttribute('tabindex') === '-1')
|
|
20
|
+
return false;
|
|
21
|
+
if (el.hasAttribute('hidden'))
|
|
22
|
+
return false;
|
|
23
|
+
const style = getComputedStyle(el);
|
|
24
|
+
if (style.display === 'none' || style.visibility === 'hidden')
|
|
25
|
+
return false;
|
|
26
|
+
const tag = el.tagName.toLowerCase();
|
|
27
|
+
if (['input', 'select', 'textarea', 'button'].includes(tag)) {
|
|
28
|
+
return !el.disabled;
|
|
29
|
+
}
|
|
30
|
+
if (tag === 'a')
|
|
31
|
+
return el.hasAttribute('href');
|
|
32
|
+
if (el.hasAttribute('tabindex') || el.hasAttribute('contenteditable'))
|
|
33
|
+
return true;
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
/** Get all focusable elements within a container, in DOM order. */
|
|
37
|
+
export function getFocusableElements(container) {
|
|
38
|
+
return Array.from(container.querySelectorAll(FOCUSABLE_SELECTOR)).filter(isElementFocusable);
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Announce a message to screen readers via an ARIA live region.
|
|
42
|
+
* Creates the region lazily and reuses it across calls.
|
|
43
|
+
*/
|
|
44
|
+
export function announce(message, priority = 'polite') {
|
|
45
|
+
if (typeof document === 'undefined')
|
|
46
|
+
return;
|
|
47
|
+
const id = `sx-announce-${priority}`;
|
|
48
|
+
let region = document.getElementById(id);
|
|
49
|
+
if (!region) {
|
|
50
|
+
region = document.createElement('div');
|
|
51
|
+
region.id = id;
|
|
52
|
+
region.setAttribute('role', 'log');
|
|
53
|
+
region.setAttribute('aria-live', priority);
|
|
54
|
+
region.setAttribute('aria-relevant', 'additions');
|
|
55
|
+
region.setAttribute('aria-atomic', 'true');
|
|
56
|
+
Object.assign(region.style, {
|
|
57
|
+
position: 'absolute',
|
|
58
|
+
width: '1px',
|
|
59
|
+
height: '1px',
|
|
60
|
+
padding: '0',
|
|
61
|
+
margin: '-1px',
|
|
62
|
+
overflow: 'hidden',
|
|
63
|
+
clip: 'rect(0, 0, 0, 0)',
|
|
64
|
+
whiteSpace: 'nowrap',
|
|
65
|
+
border: '0',
|
|
66
|
+
});
|
|
67
|
+
document.body.appendChild(region);
|
|
68
|
+
}
|
|
69
|
+
// Clear then re-set to trigger announcement
|
|
70
|
+
region.textContent = '';
|
|
71
|
+
requestAnimationFrame(() => {
|
|
72
|
+
region.textContent = message;
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
/** Check if the user prefers reduced motion. */
|
|
76
|
+
export function prefersReducedMotion() {
|
|
77
|
+
if (typeof window === 'undefined')
|
|
78
|
+
return false;
|
|
79
|
+
return window.matchMedia('(prefers-reduced-motion: reduce)').matches;
|
|
80
|
+
}
|
package/dist/utils/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { cn } from './cn.js';
|
|
2
|
-
export { createFocusTrap, generateId, Keys } from './keyboard.js';
|
|
2
|
+
export { createFocusTrap, generateId, Keys, isKey, isActivationKey, isNavigationKey, } from './keyboard.js';
|
|
3
3
|
export type { FocusTrap, Key } from './keyboard.js';
|
|
4
|
+
export { isElementFocusable, getFocusableElements, announce, prefersReducedMotion, } from './accessibility.js';
|
|
4
5
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,SAAS,CAAC;AAC7B,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,SAAS,CAAC;AAC7B,OAAO,EACN,eAAe,EACf,UAAU,EACV,IAAI,EACJ,KAAK,EACL,eAAe,EACf,eAAe,GACf,MAAM,eAAe,CAAC;AACvB,YAAY,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,EACN,kBAAkB,EAClB,oBAAoB,EACpB,QAAQ,EACR,oBAAoB,GACpB,MAAM,oBAAoB,CAAC"}
|
package/dist/utils/index.js
CHANGED
|
@@ -1,2 +1,3 @@
|
|
|
1
1
|
export { cn } from './cn.js';
|
|
2
|
-
export { createFocusTrap, generateId, Keys } from './keyboard.js';
|
|
2
|
+
export { createFocusTrap, generateId, Keys, isKey, isActivationKey, isNavigationKey, } from './keyboard.js';
|
|
3
|
+
export { isElementFocusable, getFocusableElements, announce, prefersReducedMotion, } from './accessibility.js';
|
package/dist/utils/keyboard.d.ts
CHANGED
|
@@ -23,6 +23,12 @@ export interface FocusTrap {
|
|
|
23
23
|
* Trap focus within a container (e.g. modal). Tab cycles inside; restores focus on deactivate.
|
|
24
24
|
*/
|
|
25
25
|
export declare function createFocusTrap(container: HTMLElement): FocusTrap;
|
|
26
|
+
/** Check if the key matches one of the provided keys. */
|
|
27
|
+
export declare function isKey(event: KeyboardEvent, ...keys: Key[]): boolean;
|
|
28
|
+
/** Check if the key is an activation key (Enter or Space). */
|
|
29
|
+
export declare function isActivationKey(event: KeyboardEvent): boolean;
|
|
30
|
+
/** Check if the key is a navigation key (arrows, Home, End). */
|
|
31
|
+
export declare function isNavigationKey(event: KeyboardEvent): boolean;
|
|
26
32
|
/** Unique ID for aria attributes (per-instance safe). */
|
|
27
33
|
export declare function generateId(prefix?: string): string;
|
|
28
34
|
//# sourceMappingURL=keyboard.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"keyboard.d.ts","sourceRoot":"","sources":["../../src/utils/keyboard.ts"],"names":[],"mappings":"AAAA;;;GAGG;
|
|
1
|
+
{"version":3,"file":"keyboard.d.ts","sourceRoot":"","sources":["../../src/utils/keyboard.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,eAAO,MAAM,IAAI;;;;;;;;;;;CAWP,CAAC;AAEX,MAAM,MAAM,GAAG,GAAG,CAAC,OAAO,IAAI,CAAC,CAAC,MAAM,OAAO,IAAI,CAAC,CAAC;AAEnD,MAAM,WAAW,SAAS;IACzB,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,UAAU,EAAE,MAAM,IAAI,CAAC;CACvB;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,SAAS,EAAE,WAAW,GAAG,SAAS,CAoCjE;AAED,yDAAyD;AACzD,wBAAgB,KAAK,CAAC,KAAK,EAAE,aAAa,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,OAAO,CAEnE;AAED,8DAA8D;AAC9D,wBAAgB,eAAe,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAE7D;AAED,gEAAgE;AAChE,wBAAgB,eAAe,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAU7D;AAED,yDAAyD;AACzD,wBAAgB,UAAU,CAAC,MAAM,SAAW,GAAG,MAAM,CAEpD"}
|
package/dist/utils/keyboard.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
* Keyboard and focus utilities for accessible components.
|
|
3
3
|
* WCAG 2.1 / WAI-ARIA aligned; used by Modal and other dialogs.
|
|
4
4
|
*/
|
|
5
|
+
import { getFocusableElements } from './accessibility.js';
|
|
5
6
|
export const Keys = {
|
|
6
7
|
Enter: 'Enter',
|
|
7
8
|
Space: ' ',
|
|
@@ -19,16 +20,9 @@ export const Keys = {
|
|
|
19
20
|
*/
|
|
20
21
|
export function createFocusTrap(container) {
|
|
21
22
|
let previouslyFocused = null;
|
|
22
|
-
const focusableSelector = [
|
|
23
|
-
'button:not([disabled]):not([tabindex="-1"])',
|
|
24
|
-
'[href]:not([tabindex="-1"])',
|
|
25
|
-
'input:not([disabled]):not([tabindex="-1"])',
|
|
26
|
-
'select:not([disabled]):not([tabindex="-1"])',
|
|
27
|
-
'textarea:not([disabled]):not([tabindex="-1"])',
|
|
28
|
-
'[tabindex]:not([tabindex="-1"])'
|
|
29
|
-
].join(', ');
|
|
30
23
|
function getFocusable() {
|
|
31
|
-
|
|
24
|
+
// Use shared implementation that filters invisible/disabled elements
|
|
25
|
+
return getFocusableElements(container);
|
|
32
26
|
}
|
|
33
27
|
function onKeyDown(e) {
|
|
34
28
|
if (e.key !== Keys.Tab)
|
|
@@ -61,6 +55,18 @@ export function createFocusTrap(container) {
|
|
|
61
55
|
}
|
|
62
56
|
};
|
|
63
57
|
}
|
|
58
|
+
/** Check if the key matches one of the provided keys. */
|
|
59
|
+
export function isKey(event, ...keys) {
|
|
60
|
+
return keys.includes(event.key);
|
|
61
|
+
}
|
|
62
|
+
/** Check if the key is an activation key (Enter or Space). */
|
|
63
|
+
export function isActivationKey(event) {
|
|
64
|
+
return isKey(event, Keys.Enter, Keys.Space);
|
|
65
|
+
}
|
|
66
|
+
/** Check if the key is a navigation key (arrows, Home, End). */
|
|
67
|
+
export function isNavigationKey(event) {
|
|
68
|
+
return isKey(event, Keys.ArrowUp, Keys.ArrowDown, Keys.ArrowLeft, Keys.ArrowRight, Keys.Home, Keys.End);
|
|
69
|
+
}
|
|
64
70
|
/** Unique ID for aria attributes (per-instance safe). */
|
|
65
71
|
export function generateId(prefix = 'salmex') {
|
|
66
72
|
return `${prefix}-${Math.random().toString(36).slice(2, 11)}`;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@salmexio/ui",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"description": "Salmex I/O Design System — INFRARED component library for Salmex products",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "UNLICENSED",
|
|
@@ -39,6 +39,26 @@
|
|
|
39
39
|
"svelte": "./dist/navigation/index.js",
|
|
40
40
|
"default": "./dist/navigation/index.js"
|
|
41
41
|
},
|
|
42
|
+
"./forms": {
|
|
43
|
+
"types": "./dist/forms/index.d.ts",
|
|
44
|
+
"svelte": "./dist/forms/index.js",
|
|
45
|
+
"default": "./dist/forms/index.js"
|
|
46
|
+
},
|
|
47
|
+
"./layout": {
|
|
48
|
+
"types": "./dist/layout/index.d.ts",
|
|
49
|
+
"svelte": "./dist/layout/index.js",
|
|
50
|
+
"default": "./dist/layout/index.js"
|
|
51
|
+
},
|
|
52
|
+
"./feedback": {
|
|
53
|
+
"types": "./dist/feedback/index.d.ts",
|
|
54
|
+
"svelte": "./dist/feedback/index.js",
|
|
55
|
+
"default": "./dist/feedback/index.js"
|
|
56
|
+
},
|
|
57
|
+
"./dialogs": {
|
|
58
|
+
"types": "./dist/dialogs/index.d.ts",
|
|
59
|
+
"svelte": "./dist/dialogs/index.js",
|
|
60
|
+
"default": "./dist/dialogs/index.js"
|
|
61
|
+
},
|
|
42
62
|
"./utils": {
|
|
43
63
|
"types": "./dist/utils/index.d.ts",
|
|
44
64
|
"default": "./dist/utils/index.js"
|