@digdir/designsystemet-web 1.13.2 → 1.13.3

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.
@@ -1,2 +1,2 @@
1
- const e=require(`../utils/utils.cjs`),t=`aria-describedby`,n=`data-indeterminate`,r=e.isWindows()?800:200,i=new WeakMap,a=new Map,o=new WeakMap,s=(e,t=[])=>{for(let{target:e}of t){let t=e instanceof HTMLFieldSetElement;for(let[n]of a)(t?e.contains(n):n.contains(e))&&c(n)}},c=r=>{let s=[],c=[],l=a.get(r)||[],d,m,h=!1,g=!1;for(let t of r.getElementsByTagName(`*`))if(t instanceof HTMLLabelElement&&s.push(t),!t.hidden)if(p(t))d?e.warn(`Fields should only have one input element. Use <fieldset> to group multiple fields:`,r):d=t;else{let n=t.getAttribute(`data-field`);n===`counter`&&(m=t),n===`validation`?(c.unshift(e.useId(t)),h=!0,g||=f(t)):n&&c.push(e.useId(t))}if(!d)return;m&&i.set(d,m);for(let t of s)e.attr(t,`for`,e.useId(d));let _=r.closest(`fieldset`)?.querySelector(`:scope > [data-field="validation"]`);_&&!_?.hidden&&(h=!0,g||=f(_),c.unshift(e.useId(_)));let v=e.attr(d,n);v&&(d.indeterminate=v===`true`),(d.type===`radio`||d.type===`checkbox`)&&e.attr(r,`data-clickdelegatefor`,e.useId(d));let y=(e.attr(d,t)?.trim().split(/\s+/))?.filter(e=>!l.includes(e))||[];e.attr(d,t,[...c,...y].join(` `)||null),a.set(r,c);let b=o.has(d);h&&!b?(o.set(d,e.attr(d,`aria-invalid`)),e.attr(d,`aria-invalid`,`true`)):!h&&b&&(e.attr(d,`aria-invalid`,o.get(d)),o.delete(d)),u(d)},l={over:`%d tegn for mye`,under:`%d tegn igjen`},u=t=>{let n=t.target||t,r=i.get(n);if(r?.isConnected){let i=(Number(e.attr(r,`data-limit`))||0)-n.value.length,a=i<0?`over`:`under`,o=(e.attrOrCSS(r,`data-${a}`)||l[a])?.replace(`%d`,`${Math.abs(i)}`);e.attr(r,`data-label`,o),e.attr(r,`data-state`,a),e.attr(r,`data-color`,i<0?`danger`:null),t.type===`input`&&o&&d(n,o)}n instanceof HTMLTextAreaElement&&(n.style.setProperty(`--_ds-field-sizing`,`auto`),n.style.setProperty(`--_ds-field-sizing`,`${n.scrollHeight}px`))},d=e.debounce((t,n)=>{document.activeElement===t&&e.announce(n)},r),f=e=>e.getAttribute(`data-color`)!==`success`,p=e=>e instanceof HTMLElement&&`validity`in e&&!(e instanceof HTMLButtonElement)&&e.type!==`hidden`;var m=class extends e.DSElement{connectedCallback(){a.set(this,[]),c(this)}disconnectedCallback(){a.delete(this)}};e.customElements.define(`ds-field`,m),e.onHotReload(`field`,()=>[e.on(document,`input`,u,e.QUICK_EVENT),e.onMutation(document,s,{attributeFilter:[`data-field`,`data-limit`,`hidden`,`id`,`value`,n],attributes:!0,childList:!0,subtree:!0})]),exports.DSFieldElement=m;
1
+ const e=require(`../utils/utils.cjs`),t=`aria-invalid`,n=`aria-describedby`,r=`data-indeterminate`,i=e.isWindows()?800:200,a=new WeakMap,o=new Map,s=new WeakSet,c=(e,t=[])=>{for(let{target:e}of t){let t=e instanceof HTMLFieldSetElement;for(let[n]of o)(t?e.contains(n):n.contains(e))&&l(n)}},l=i=>{let c=[],l=[],u=o.get(i)||[],f,h,g=!1,_=!1;for(let t of i.getElementsByTagName(`*`))if(t instanceof HTMLLabelElement&&c.push(t),!t.hidden)if(m(t))f?e.warn(`Fields should only have one input element. Use <fieldset> to group multiple fields:`,i):f=t;else{let n=t.getAttribute(`data-field`);n===`counter`&&(h=t),n===`validation`?(l.unshift(e.useId(t)),g=!0,_||=p(t)):n&&l.push(e.useId(t))}if(!f)return;h&&a.set(f,h);for(let t of c)e.attr(t,`for`,e.useId(f));let v=i.closest(`fieldset`)?.querySelector(`:scope > [data-field="validation"]`);v&&!v?.hidden&&(g=!0,_||=p(v),l.unshift(e.useId(v)));let y=e.attr(f,r);y&&(f.indeterminate=y===`true`),(f.type===`radio`||f.type===`checkbox`)&&e.attr(i,`data-clickdelegatefor`,e.useId(f));let b=(e.attr(f,n)?.trim().split(/\s+/))?.filter(e=>!u.includes(e))||[];e.attr(f,n,[...l,...b].join(` `)||null),o.set(i,l);let x=s.has(f);g&&!x&&!f.hasAttribute(t)?(e.attr(f,t,`true`),s.add(f)):!g&&x&&(e.attr(f,t,null),s.delete(f)),d(f)},u={over:`%d tegn for mye`,under:`%d tegn igjen`},d=t=>{let n=t.target||t,r=a.get(n);if(r?.isConnected){let i=(Number(e.attr(r,`data-limit`))||0)-n.value.length,a=i<0?`over`:`under`,o=(e.attrOrCSS(r,`data-${a}`)||u[a])?.replace(`%d`,`${Math.abs(i)}`);e.attr(r,`data-label`,o),e.attr(r,`data-state`,a),e.attr(r,`data-color`,i<0?`danger`:null),t.type===`input`&&o&&f(n,o)}n instanceof HTMLTextAreaElement&&(n.style.setProperty(`--_ds-field-sizing`,`auto`),n.style.setProperty(`--_ds-field-sizing`,`${n.scrollHeight}px`))},f=e.debounce((t,n)=>{document.activeElement===t&&e.announce(n)},i),p=e=>e.getAttribute(`data-color`)!==`success`,m=e=>e instanceof HTMLElement&&`validity`in e&&!(e instanceof HTMLButtonElement)&&e.type!==`hidden`;var h=class extends e.DSElement{connectedCallback(){o.set(this,[]),l(this)}disconnectedCallback(){o.delete(this)}};e.customElements.define(`ds-field`,h),e.onHotReload(`field`,()=>[e.on(document,`input`,d,e.QUICK_EVENT),e.onMutation(document,c,{attributeFilter:[`data-field`,`data-limit`,`hidden`,`id`,`value`,r],attributes:!0,childList:!0,subtree:!0})]),exports.DSFieldElement=h;
2
2
  //# sourceMappingURL=field.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"field.cjs","names":["isWindows","useId","attr","attrOrCSS","debounce","DSElement","customElements","onHotReload","on","QUICK_EVENT","onMutation"],"sources":["../../../src/field/field.ts"],"sourcesContent":["import {\n announce,\n attr,\n attrOrCSS,\n customElements,\n DSElement,\n debounce,\n isWindows,\n on,\n onHotReload,\n onMutation,\n QUICK_EVENT,\n useId,\n warn,\n} from '../utils/utils';\n\n// TODO: Document that Validation must be hidden with \"hidden\" attribute (or completely removed from DOM), not display: none\ndeclare global {\n interface HTMLElementTagNameMap {\n 'ds-field': DSFieldElement;\n }\n}\n\nconst ATTR_DESCRIBEDBY = 'aria-describedby';\nconst ATTR_INDETERMINATE = 'data-indeterminate';\nconst COUNTER_DEBOUNCE = isWindows() ? 800 : 200; // Longer debounce on Windows due to NVDA performance\nconst COUNTS = new WeakMap<HTMLInputElement, Element>(); // Using WeakMap so removed inputs/counts does not cause memory leaks\nconst FIELDS = new Map<DSFieldElement, string[]>(); // Map of Field and its describedby IDs so we can identify the ones we add/remove\nconst VALIDATIONS = new WeakMap<HTMLInputElement>(); // Used to ensure we only take control of aria-invalid if there current is or has been a validation element\nconst WARNING_MULTIPLE_INPUTS = `Fields should only have one input element. Use <fieldset> to group multiple fields:`;\n\nconst handleFieldMutations = (_doc: Node, records: MutationRecord[] = []) => {\n for (const { target } of records) {\n const isFieldset = target instanceof HTMLFieldSetElement;\n for (const [field] of FIELDS)\n if (isFieldset ? target.contains(field) : field.contains(target))\n handleFieldMutation(field);\n }\n};\n\nconst handleFieldMutation = (field: DSFieldElement) => {\n const labels: HTMLLabelElement[] = [];\n const nextDescs: string[] = []; // Keep track of descriptions we are adding in this mutation\n const prevDescs = FIELDS.get(field) || []; // Retrieve previously managed IDs for this field\n let input: HTMLInputElement | undefined;\n let counter: Element | undefined;\n let hasValidation = false;\n let invalid = false;\n\n for (const el of field.getElementsByTagName('*')) {\n if (el instanceof HTMLLabelElement) labels.push(el);\n if ((el as HTMLElement).hidden) continue; // Skip hidden elements except labels\n if (isInputLike(el)) {\n if (input) warn(WARNING_MULTIPLE_INPUTS, field);\n else input = el; // Only register if visible input\n } else {\n const type = el.getAttribute('data-field'); // Using getAttribute instead of attr for best performance\n if (type === 'counter') counter = el;\n if (type === 'validation') {\n nextDescs.unshift(useId(el));\n hasValidation = true;\n invalid = invalid || isInvalid(el);\n } else if (type) nextDescs.push(useId(el)); // Adds both counter and descriptions\n }\n }\n\n if (!input) return; // Do not warn about missing input as virtual DOM libraries might give false positives\n if (counter) COUNTS.set(input, counter);\n for (const label of labels) attr(label, 'for', useId(input));\n\n const fieldsetValidation = field\n .closest('fieldset')\n ?.querySelector<HTMLElement>(':scope > [data-field=\"validation\"]');\n\n // Connect fieldset validation to inputs\n if (fieldsetValidation && !fieldsetValidation?.hidden) {\n hasValidation = true;\n invalid = invalid || isInvalid(fieldsetValidation);\n nextDescs.unshift(useId(fieldsetValidation));\n }\n\n // Add support for data-indeterminate attribute as this normally can only be set by javascript\n const indeterminate = attr(input, ATTR_INDETERMINATE);\n if (indeterminate) input.indeterminate = indeterminate === 'true';\n\n // Expand click area to ds-field if radio/checkbox\n const isBoolish = input.type === 'radio' || input.type === 'checkbox';\n if (isBoolish) attr(field, 'data-clickdelegatefor', useId(input));\n\n // Setup aria-describedby, but repsect existing ids in aria-describedby\n const describedby = attr(input, ATTR_DESCRIBEDBY)?.trim().split(/\\s+/);\n const keep = describedby?.filter((id) => !prevDescs.includes(id)) || []; // Find non-ds-field-managed aria-describedby IDs\n attr(input, ATTR_DESCRIBEDBY, [...nextDescs, ...keep].join(' ') || null);\n FIELDS.set(field, nextDescs);\n\n // Only manage aria-invalid when field has validation elements\n const hadValidation = VALIDATIONS.has(input);\n if (hasValidation && !hadValidation) {\n VALIDATIONS.set(input, attr(input, 'aria-invalid')); // Store previous attribute to enable reverting state\n attr(input, 'aria-invalid', 'true');\n } else if (!hasValidation && hadValidation) {\n attr(input, 'aria-invalid', VALIDATIONS.get(input)); // Revert to previous state if validation element was removed\n VALIDATIONS.delete(input);\n }\n\n handleFieldInput(input); // Update counter and textarea sizing\n};\n\n// Used as fallback in tests when CSS is not loaded\nconst TEXTS = {\n over: '%d tegn for mye',\n under: '%d tegn igjen',\n};\n\nconst handleFieldInput = (e: Event | Element) => {\n const input = ((e as Event).target || e) as HTMLInputElement;\n const counter = COUNTS.get(input);\n\n if (counter?.isConnected) {\n const limit = Number(attr(counter, 'data-limit')) || 0;\n const count = limit - input.value.length;\n const state = count < 0 ? 'over' : 'under';\n const label = (\n attrOrCSS(counter, `data-${state}`) || TEXTS[state]\n )?.replace('%d', `${Math.abs(count)}`);\n\n attr(counter, 'data-label', label); // Using attribute to prevent hydation errors, not using aria-label to make axe tests happy\n attr(counter, 'data-state', state);\n attr(counter, 'data-color', count < 0 ? 'danger' : null);\n\n // Only update live region when user is actually typing\n if ((e as Event).type === 'input' && label)\n debouncedCounterLiveRegion(input, label); // Debounce live region to avoid NVDA interupting announcing typed text\n }\n if (input instanceof HTMLTextAreaElement) {\n input.style.setProperty('--_ds-field-sizing', 'auto');\n input.style.setProperty('--_ds-field-sizing', `${input.scrollHeight}px`);\n }\n};\n\nconst debouncedCounterLiveRegion = debounce((input: Element, text: string) => {\n if (document.activeElement === input) announce(text); // Only announce if input is still focused\n}, COUNTER_DEBOUNCE);\n\nconst isInvalid = (el: Element) => el.getAttribute('data-color') !== 'success';\nconst isInputLike = (el: unknown): el is HTMLInputElement =>\n el instanceof HTMLElement &&\n 'validity' in el && // Adds support for custom elements implemeted with attachInternals()\n !(el instanceof HTMLButtonElement) && // But skip <button> elements\n (el as HTMLInputElement).type !== 'hidden'; // And skip input type=\"hidden\"\n\n// Custom element is used to performantly keep track of fields on the page\nexport class DSFieldElement extends DSElement {\n connectedCallback() {\n FIELDS.set(this, []); // Register field\n handleFieldMutation(this); // Initial setup\n }\n disconnectedCallback() {\n FIELDS.delete(this);\n }\n}\n\ncustomElements.define('ds-field', DSFieldElement);\n\nonHotReload('field', () => [\n on(document, 'input', handleFieldInput, QUICK_EVENT),\n onMutation(document, handleFieldMutations, {\n attributeFilter: [\n 'data-field',\n 'data-limit',\n 'hidden', // Needed to check validation visibility\n 'id', // Needed to sync label \"for\" when ID of input/selec/textarea changes\n 'value', // Needed to detect changes in controlled React inputs as they do not trigger input events\n ATTR_INDETERMINATE,\n ],\n attributes: true,\n childList: true,\n subtree: true,\n }),\n]);\n"],"mappings":"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"}
1
+ {"version":3,"file":"field.cjs","names":["isWindows","useId","attr","attrOrCSS","debounce","DSElement","customElements","onHotReload","on","QUICK_EVENT","onMutation"],"sources":["../../../src/field/field.ts"],"sourcesContent":["import {\n announce,\n attr,\n attrOrCSS,\n customElements,\n DSElement,\n debounce,\n isWindows,\n on,\n onHotReload,\n onMutation,\n QUICK_EVENT,\n useId,\n warn,\n} from '../utils/utils';\n\n// TODO: Document that Validation must be hidden with \"hidden\" attribute (or completely removed from DOM), not display: none\ndeclare global {\n interface HTMLElementTagNameMap {\n 'ds-field': DSFieldElement;\n }\n}\n\nconst ATTR_INVALID = 'aria-invalid';\nconst ATTR_DESCRIBEDBY = 'aria-describedby';\nconst ATTR_INDETERMINATE = 'data-indeterminate';\nconst COUNTER_DEBOUNCE = isWindows() ? 800 : 200; // Longer debounce on Windows due to NVDA performance\nconst COUNTS = new WeakMap<HTMLInputElement, Element>(); // Using WeakMap so removed inputs/counts does not cause memory leaks\nconst FIELDS = new Map<DSFieldElement, string[]>(); // Map of Field and its describedby IDs so we can identify the ones we add/remove\nconst VALIDATIONS = new WeakSet<HTMLInputElement>(); // Used to ensure we only take control of aria-invalid if the current is or has been a validation element\nconst WARNING_MULTIPLE_INPUTS = `Fields should only have one input element. Use <fieldset> to group multiple fields:`;\n\nconst handleFieldMutations = (_doc: Node, records: MutationRecord[] = []) => {\n for (const { target } of records) {\n const isFieldset = target instanceof HTMLFieldSetElement;\n for (const [field] of FIELDS)\n if (isFieldset ? target.contains(field) : field.contains(target))\n handleFieldMutation(field);\n }\n};\n\nconst handleFieldMutation = (field: DSFieldElement) => {\n const labels: HTMLLabelElement[] = [];\n const nextDescs: string[] = []; // Keep track of descriptions we are adding in this mutation\n const prevDescs = FIELDS.get(field) || []; // Retrieve previously managed IDs for this field\n let input: HTMLInputElement | undefined;\n let counter: Element | undefined;\n let hasValidation = false;\n let invalid = false;\n\n for (const el of field.getElementsByTagName('*')) {\n if (el instanceof HTMLLabelElement) labels.push(el);\n if ((el as HTMLElement).hidden) continue; // Skip hidden elements except labels\n if (isInputLike(el)) {\n if (input) warn(WARNING_MULTIPLE_INPUTS, field);\n else input = el; // Only register if visible input\n } else {\n const type = el.getAttribute('data-field'); // Using getAttribute instead of attr for best performance\n if (type === 'counter') counter = el;\n if (type === 'validation') {\n nextDescs.unshift(useId(el));\n hasValidation = true;\n invalid = invalid || isInvalid(el);\n } else if (type) nextDescs.push(useId(el)); // Adds both counter and descriptions\n }\n }\n\n if (!input) return; // Do not warn about missing input as virtual DOM libraries might give false positives\n if (counter) COUNTS.set(input, counter);\n for (const label of labels) attr(label, 'for', useId(input));\n\n const fieldsetValidation = field\n .closest('fieldset')\n ?.querySelector<HTMLElement>(':scope > [data-field=\"validation\"]');\n\n // Connect fieldset validation to inputs\n if (fieldsetValidation && !fieldsetValidation?.hidden) {\n hasValidation = true;\n invalid = invalid || isInvalid(fieldsetValidation);\n nextDescs.unshift(useId(fieldsetValidation));\n }\n\n // Add support for data-indeterminate attribute as this normally can only be set by javascript\n const indeterminate = attr(input, ATTR_INDETERMINATE);\n if (indeterminate) input.indeterminate = indeterminate === 'true';\n\n // Expand click area to ds-field if radio/checkbox\n const isBoolish = input.type === 'radio' || input.type === 'checkbox';\n if (isBoolish) attr(field, 'data-clickdelegatefor', useId(input));\n\n // Setup aria-describedby, but repsect existing ids in aria-describedby\n const describedby = attr(input, ATTR_DESCRIBEDBY)?.trim().split(/\\s+/);\n const keep = describedby?.filter((id) => !prevDescs.includes(id)) || []; // Find non-ds-field-managed aria-describedby IDs\n attr(input, ATTR_DESCRIBEDBY, [...nextDescs, ...keep].join(' ') || null);\n FIELDS.set(field, nextDescs);\n\n // Only manage aria-invalid when field has validation elements, and aria-invalid does not already exist\n const hadValidation = VALIDATIONS.has(input);\n if (hasValidation && !hadValidation && !input.hasAttribute(ATTR_INVALID)) {\n attr(input, ATTR_INVALID, 'true');\n VALIDATIONS.add(input);\n } else if (!hasValidation && hadValidation) {\n attr(input, ATTR_INVALID, null); // Remove aria-invalid\n VALIDATIONS.delete(input);\n }\n\n handleFieldInput(input); // Update counter and textarea sizing\n};\n\n// Used as fallback in tests when CSS is not loaded\nconst TEXTS = {\n over: '%d tegn for mye',\n under: '%d tegn igjen',\n};\n\nconst handleFieldInput = (e: Event | Element) => {\n const input = ((e as Event).target || e) as HTMLInputElement;\n const counter = COUNTS.get(input);\n\n if (counter?.isConnected) {\n const limit = Number(attr(counter, 'data-limit')) || 0;\n const count = limit - input.value.length;\n const state = count < 0 ? 'over' : 'under';\n const label = (\n attrOrCSS(counter, `data-${state}`) || TEXTS[state]\n )?.replace('%d', `${Math.abs(count)}`);\n\n attr(counter, 'data-label', label); // Using attribute to prevent hydation errors, not using aria-label to make axe tests happy\n attr(counter, 'data-state', state);\n attr(counter, 'data-color', count < 0 ? 'danger' : null);\n\n // Only update live region when user is actually typing\n if ((e as Event).type === 'input' && label)\n debouncedCounterLiveRegion(input, label); // Debounce live region to avoid NVDA interupting announcing typed text\n }\n if (input instanceof HTMLTextAreaElement) {\n input.style.setProperty('--_ds-field-sizing', 'auto');\n input.style.setProperty('--_ds-field-sizing', `${input.scrollHeight}px`);\n }\n};\n\nconst debouncedCounterLiveRegion = debounce((input: Element, text: string) => {\n if (document.activeElement === input) announce(text); // Only announce if input is still focused\n}, COUNTER_DEBOUNCE);\n\nconst isInvalid = (el: Element) => el.getAttribute('data-color') !== 'success';\nconst isInputLike = (el: unknown): el is HTMLInputElement =>\n el instanceof HTMLElement &&\n 'validity' in el && // Adds support for custom elements implemeted with attachInternals()\n !(el instanceof HTMLButtonElement) && // But skip <button> elements\n (el as HTMLInputElement).type !== 'hidden'; // And skip input type=\"hidden\"\n\n// Custom element is used to performantly keep track of fields on the page\nexport class DSFieldElement extends DSElement {\n connectedCallback() {\n FIELDS.set(this, []); // Register field\n handleFieldMutation(this); // Initial setup\n }\n disconnectedCallback() {\n FIELDS.delete(this);\n }\n}\n\ncustomElements.define('ds-field', DSFieldElement);\n\nonHotReload('field', () => [\n on(document, 'input', handleFieldInput, QUICK_EVENT),\n onMutation(document, handleFieldMutations, {\n attributeFilter: [\n 'data-field',\n 'data-limit',\n 'hidden', // Needed to check validation visibility\n 'id', // Needed to sync label \"for\" when ID of input/selec/textarea changes\n 'value', // Needed to detect changes in controlled React inputs as they do not trigger input events\n ATTR_INDETERMINATE,\n ],\n attributes: true,\n childList: true,\n subtree: true,\n }),\n]);\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import{DSElement as e,QUICK_EVENT as t,announce as n,attr as r,attrOrCSS as i,customElements as a,debounce as o,isWindows as s,on as c,onHotReload as l,onMutation as u,useId as d,warn as f}from"../utils/utils.js";const p=`aria-describedby`,m=`data-indeterminate`,h=s()?800:200,g=new WeakMap,_=new Map,v=new WeakMap,y=(e,t=[])=>{for(let{target:e}of t){let t=e instanceof HTMLFieldSetElement;for(let[n]of _)(t?e.contains(n):n.contains(e))&&b(n)}},b=e=>{let t=[],n=[],i=_.get(e)||[],a,o,s=!1,c=!1;for(let r of e.getElementsByTagName(`*`))if(r instanceof HTMLLabelElement&&t.push(r),!r.hidden)if(T(r))a?f(`Fields should only have one input element. Use <fieldset> to group multiple fields:`,e):a=r;else{let e=r.getAttribute(`data-field`);e===`counter`&&(o=r),e===`validation`?(n.unshift(d(r)),s=!0,c||=w(r)):e&&n.push(d(r))}if(!a)return;o&&g.set(a,o);for(let e of t)r(e,`for`,d(a));let l=e.closest(`fieldset`)?.querySelector(`:scope > [data-field="validation"]`);l&&!l?.hidden&&(s=!0,c||=w(l),n.unshift(d(l)));let u=r(a,m);u&&(a.indeterminate=u===`true`),(a.type===`radio`||a.type===`checkbox`)&&r(e,`data-clickdelegatefor`,d(a));let h=(r(a,p)?.trim().split(/\s+/))?.filter(e=>!i.includes(e))||[];r(a,p,[...n,...h].join(` `)||null),_.set(e,n);let y=v.has(a);s&&!y?(v.set(a,r(a,`aria-invalid`)),r(a,`aria-invalid`,`true`)):!s&&y&&(r(a,`aria-invalid`,v.get(a)),v.delete(a)),S(a)},x={over:`%d tegn for mye`,under:`%d tegn igjen`},S=e=>{let t=e.target||e,n=g.get(t);if(n?.isConnected){let a=(Number(r(n,`data-limit`))||0)-t.value.length,o=a<0?`over`:`under`,s=(i(n,`data-${o}`)||x[o])?.replace(`%d`,`${Math.abs(a)}`);r(n,`data-label`,s),r(n,`data-state`,o),r(n,`data-color`,a<0?`danger`:null),e.type===`input`&&s&&C(t,s)}t instanceof HTMLTextAreaElement&&(t.style.setProperty(`--_ds-field-sizing`,`auto`),t.style.setProperty(`--_ds-field-sizing`,`${t.scrollHeight}px`))},C=o((e,t)=>{document.activeElement===e&&n(t)},h),w=e=>e.getAttribute(`data-color`)!==`success`,T=e=>e instanceof HTMLElement&&`validity`in e&&!(e instanceof HTMLButtonElement)&&e.type!==`hidden`;var E=class extends e{connectedCallback(){_.set(this,[]),b(this)}disconnectedCallback(){_.delete(this)}};a.define(`ds-field`,E),l(`field`,()=>[c(document,`input`,S,t),u(document,y,{attributeFilter:[`data-field`,`data-limit`,`hidden`,`id`,`value`,m],attributes:!0,childList:!0,subtree:!0})]);export{E as DSFieldElement};
1
+ import{DSElement as e,QUICK_EVENT as t,announce as n,attr as r,attrOrCSS as i,customElements as a,debounce as o,isWindows as s,on as c,onHotReload as l,onMutation as u,useId as d,warn as f}from"../utils/utils.js";const p=`aria-invalid`,m=`aria-describedby`,h=`data-indeterminate`,g=s()?800:200,_=new WeakMap,v=new Map,y=new WeakSet,b=(e,t=[])=>{for(let{target:e}of t){let t=e instanceof HTMLFieldSetElement;for(let[n]of v)(t?e.contains(n):n.contains(e))&&x(n)}},x=e=>{let t=[],n=[],i=v.get(e)||[],a,o,s=!1,c=!1;for(let r of e.getElementsByTagName(`*`))if(r instanceof HTMLLabelElement&&t.push(r),!r.hidden)if(E(r))a?f(`Fields should only have one input element. Use <fieldset> to group multiple fields:`,e):a=r;else{let e=r.getAttribute(`data-field`);e===`counter`&&(o=r),e===`validation`?(n.unshift(d(r)),s=!0,c||=T(r)):e&&n.push(d(r))}if(!a)return;o&&_.set(a,o);for(let e of t)r(e,`for`,d(a));let l=e.closest(`fieldset`)?.querySelector(`:scope > [data-field="validation"]`);l&&!l?.hidden&&(s=!0,c||=T(l),n.unshift(d(l)));let u=r(a,h);u&&(a.indeterminate=u===`true`),(a.type===`radio`||a.type===`checkbox`)&&r(e,`data-clickdelegatefor`,d(a));let g=(r(a,m)?.trim().split(/\s+/))?.filter(e=>!i.includes(e))||[];r(a,m,[...n,...g].join(` `)||null),v.set(e,n);let b=y.has(a);s&&!b&&!a.hasAttribute(p)?(r(a,p,`true`),y.add(a)):!s&&b&&(r(a,p,null),y.delete(a)),C(a)},S={over:`%d tegn for mye`,under:`%d tegn igjen`},C=e=>{let t=e.target||e,n=_.get(t);if(n?.isConnected){let a=(Number(r(n,`data-limit`))||0)-t.value.length,o=a<0?`over`:`under`,s=(i(n,`data-${o}`)||S[o])?.replace(`%d`,`${Math.abs(a)}`);r(n,`data-label`,s),r(n,`data-state`,o),r(n,`data-color`,a<0?`danger`:null),e.type===`input`&&s&&w(t,s)}t instanceof HTMLTextAreaElement&&(t.style.setProperty(`--_ds-field-sizing`,`auto`),t.style.setProperty(`--_ds-field-sizing`,`${t.scrollHeight}px`))},w=o((e,t)=>{document.activeElement===e&&n(t)},g),T=e=>e.getAttribute(`data-color`)!==`success`,E=e=>e instanceof HTMLElement&&`validity`in e&&!(e instanceof HTMLButtonElement)&&e.type!==`hidden`;var D=class extends e{connectedCallback(){v.set(this,[]),x(this)}disconnectedCallback(){v.delete(this)}};a.define(`ds-field`,D),l(`field`,()=>[c(document,`input`,C,t),u(document,b,{attributeFilter:[`data-field`,`data-limit`,`hidden`,`id`,`value`,h],attributes:!0,childList:!0,subtree:!0})]);export{D as DSFieldElement};
2
2
  //# sourceMappingURL=field.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"field.js","names":[],"sources":["../../../src/field/field.ts"],"sourcesContent":["import {\n announce,\n attr,\n attrOrCSS,\n customElements,\n DSElement,\n debounce,\n isWindows,\n on,\n onHotReload,\n onMutation,\n QUICK_EVENT,\n useId,\n warn,\n} from '../utils/utils';\n\n// TODO: Document that Validation must be hidden with \"hidden\" attribute (or completely removed from DOM), not display: none\ndeclare global {\n interface HTMLElementTagNameMap {\n 'ds-field': DSFieldElement;\n }\n}\n\nconst ATTR_DESCRIBEDBY = 'aria-describedby';\nconst ATTR_INDETERMINATE = 'data-indeterminate';\nconst COUNTER_DEBOUNCE = isWindows() ? 800 : 200; // Longer debounce on Windows due to NVDA performance\nconst COUNTS = new WeakMap<HTMLInputElement, Element>(); // Using WeakMap so removed inputs/counts does not cause memory leaks\nconst FIELDS = new Map<DSFieldElement, string[]>(); // Map of Field and its describedby IDs so we can identify the ones we add/remove\nconst VALIDATIONS = new WeakMap<HTMLInputElement>(); // Used to ensure we only take control of aria-invalid if there current is or has been a validation element\nconst WARNING_MULTIPLE_INPUTS = `Fields should only have one input element. Use <fieldset> to group multiple fields:`;\n\nconst handleFieldMutations = (_doc: Node, records: MutationRecord[] = []) => {\n for (const { target } of records) {\n const isFieldset = target instanceof HTMLFieldSetElement;\n for (const [field] of FIELDS)\n if (isFieldset ? target.contains(field) : field.contains(target))\n handleFieldMutation(field);\n }\n};\n\nconst handleFieldMutation = (field: DSFieldElement) => {\n const labels: HTMLLabelElement[] = [];\n const nextDescs: string[] = []; // Keep track of descriptions we are adding in this mutation\n const prevDescs = FIELDS.get(field) || []; // Retrieve previously managed IDs for this field\n let input: HTMLInputElement | undefined;\n let counter: Element | undefined;\n let hasValidation = false;\n let invalid = false;\n\n for (const el of field.getElementsByTagName('*')) {\n if (el instanceof HTMLLabelElement) labels.push(el);\n if ((el as HTMLElement).hidden) continue; // Skip hidden elements except labels\n if (isInputLike(el)) {\n if (input) warn(WARNING_MULTIPLE_INPUTS, field);\n else input = el; // Only register if visible input\n } else {\n const type = el.getAttribute('data-field'); // Using getAttribute instead of attr for best performance\n if (type === 'counter') counter = el;\n if (type === 'validation') {\n nextDescs.unshift(useId(el));\n hasValidation = true;\n invalid = invalid || isInvalid(el);\n } else if (type) nextDescs.push(useId(el)); // Adds both counter and descriptions\n }\n }\n\n if (!input) return; // Do not warn about missing input as virtual DOM libraries might give false positives\n if (counter) COUNTS.set(input, counter);\n for (const label of labels) attr(label, 'for', useId(input));\n\n const fieldsetValidation = field\n .closest('fieldset')\n ?.querySelector<HTMLElement>(':scope > [data-field=\"validation\"]');\n\n // Connect fieldset validation to inputs\n if (fieldsetValidation && !fieldsetValidation?.hidden) {\n hasValidation = true;\n invalid = invalid || isInvalid(fieldsetValidation);\n nextDescs.unshift(useId(fieldsetValidation));\n }\n\n // Add support for data-indeterminate attribute as this normally can only be set by javascript\n const indeterminate = attr(input, ATTR_INDETERMINATE);\n if (indeterminate) input.indeterminate = indeterminate === 'true';\n\n // Expand click area to ds-field if radio/checkbox\n const isBoolish = input.type === 'radio' || input.type === 'checkbox';\n if (isBoolish) attr(field, 'data-clickdelegatefor', useId(input));\n\n // Setup aria-describedby, but repsect existing ids in aria-describedby\n const describedby = attr(input, ATTR_DESCRIBEDBY)?.trim().split(/\\s+/);\n const keep = describedby?.filter((id) => !prevDescs.includes(id)) || []; // Find non-ds-field-managed aria-describedby IDs\n attr(input, ATTR_DESCRIBEDBY, [...nextDescs, ...keep].join(' ') || null);\n FIELDS.set(field, nextDescs);\n\n // Only manage aria-invalid when field has validation elements\n const hadValidation = VALIDATIONS.has(input);\n if (hasValidation && !hadValidation) {\n VALIDATIONS.set(input, attr(input, 'aria-invalid')); // Store previous attribute to enable reverting state\n attr(input, 'aria-invalid', 'true');\n } else if (!hasValidation && hadValidation) {\n attr(input, 'aria-invalid', VALIDATIONS.get(input)); // Revert to previous state if validation element was removed\n VALIDATIONS.delete(input);\n }\n\n handleFieldInput(input); // Update counter and textarea sizing\n};\n\n// Used as fallback in tests when CSS is not loaded\nconst TEXTS = {\n over: '%d tegn for mye',\n under: '%d tegn igjen',\n};\n\nconst handleFieldInput = (e: Event | Element) => {\n const input = ((e as Event).target || e) as HTMLInputElement;\n const counter = COUNTS.get(input);\n\n if (counter?.isConnected) {\n const limit = Number(attr(counter, 'data-limit')) || 0;\n const count = limit - input.value.length;\n const state = count < 0 ? 'over' : 'under';\n const label = (\n attrOrCSS(counter, `data-${state}`) || TEXTS[state]\n )?.replace('%d', `${Math.abs(count)}`);\n\n attr(counter, 'data-label', label); // Using attribute to prevent hydation errors, not using aria-label to make axe tests happy\n attr(counter, 'data-state', state);\n attr(counter, 'data-color', count < 0 ? 'danger' : null);\n\n // Only update live region when user is actually typing\n if ((e as Event).type === 'input' && label)\n debouncedCounterLiveRegion(input, label); // Debounce live region to avoid NVDA interupting announcing typed text\n }\n if (input instanceof HTMLTextAreaElement) {\n input.style.setProperty('--_ds-field-sizing', 'auto');\n input.style.setProperty('--_ds-field-sizing', `${input.scrollHeight}px`);\n }\n};\n\nconst debouncedCounterLiveRegion = debounce((input: Element, text: string) => {\n if (document.activeElement === input) announce(text); // Only announce if input is still focused\n}, COUNTER_DEBOUNCE);\n\nconst isInvalid = (el: Element) => el.getAttribute('data-color') !== 'success';\nconst isInputLike = (el: unknown): el is HTMLInputElement =>\n el instanceof HTMLElement &&\n 'validity' in el && // Adds support for custom elements implemeted with attachInternals()\n !(el instanceof HTMLButtonElement) && // But skip <button> elements\n (el as HTMLInputElement).type !== 'hidden'; // And skip input type=\"hidden\"\n\n// Custom element is used to performantly keep track of fields on the page\nexport class DSFieldElement extends DSElement {\n connectedCallback() {\n FIELDS.set(this, []); // Register field\n handleFieldMutation(this); // Initial setup\n }\n disconnectedCallback() {\n FIELDS.delete(this);\n }\n}\n\ncustomElements.define('ds-field', DSFieldElement);\n\nonHotReload('field', () => [\n on(document, 'input', handleFieldInput, QUICK_EVENT),\n onMutation(document, handleFieldMutations, {\n attributeFilter: [\n 'data-field',\n 'data-limit',\n 'hidden', // Needed to check validation visibility\n 'id', // Needed to sync label \"for\" when ID of input/selec/textarea changes\n 'value', // Needed to detect changes in controlled React inputs as they do not trigger input events\n ATTR_INDETERMINATE,\n ],\n attributes: true,\n childList: true,\n subtree: true,\n }),\n]);\n"],"mappings":"qNAuBA,MAAM,EAAmB,mBACnB,EAAqB,qBACrB,EAAmB,GAAW,CAAG,IAAM,IACvC,EAAS,IAAI,QACb,EAAS,IAAI,IACb,EAAc,IAAI,QAGlB,GAAwB,EAAY,EAA4B,EAAE,GAAK,CAC3E,IAAK,GAAM,CAAE,YAAY,EAAS,CAChC,IAAM,EAAa,aAAkB,oBACrC,IAAK,GAAM,CAAC,KAAU,GAChB,EAAa,EAAO,SAAS,EAAM,CAAG,EAAM,SAAS,EAAO,GAC9D,EAAoB,EAAM,GAI5B,EAAuB,GAA0B,CACrD,IAAM,EAA6B,EAAE,CAC/B,EAAsB,EAAE,CACxB,EAAY,EAAO,IAAI,EAAM,EAAI,EAAE,CACrC,EACA,EACA,EAAgB,GAChB,EAAU,GAEd,IAAK,IAAM,KAAM,EAAM,qBAAqB,IAAI,CAC9C,GAAI,aAAc,kBAAkB,EAAO,KAAK,EAAG,CAC9C,GAAmB,OACxB,GAAI,EAAY,EAAG,CACb,EAAO,EAAK,sFAAyB,EAAM,CAC1C,EAAQ,MACR,CACL,IAAM,EAAO,EAAG,aAAa,aAAa,CACtC,IAAS,YAAW,EAAU,GAC9B,IAAS,cACX,EAAU,QAAQ,EAAM,EAAG,CAAC,CAC5B,EAAgB,GAChB,IAAqB,EAAU,EAAG,EACzB,GAAM,EAAU,KAAK,EAAM,EAAG,CAAC,CAI9C,GAAI,CAAC,EAAO,OACR,GAAS,EAAO,IAAI,EAAO,EAAQ,CACvC,IAAK,IAAM,KAAS,EAAQ,EAAK,EAAO,MAAO,EAAM,EAAM,CAAC,CAE5D,IAAM,EAAqB,EACxB,QAAQ,WAAW,EAClB,cAA2B,qCAAqC,CAGhE,GAAsB,CAAC,GAAoB,SAC7C,EAAgB,GAChB,IAAqB,EAAU,EAAmB,CAClD,EAAU,QAAQ,EAAM,EAAmB,CAAC,EAI9C,IAAM,EAAgB,EAAK,EAAO,EAAmB,CACjD,IAAe,EAAM,cAAgB,IAAkB,SAGzC,EAAM,OAAS,SAAW,EAAM,OAAS,aAC5C,EAAK,EAAO,wBAAyB,EAAM,EAAM,CAAC,CAIjE,IAAM,GADc,EAAK,EAAO,EAAiB,EAAE,MAAM,CAAC,MAAM,MAAM,GAC5C,OAAQ,GAAO,CAAC,EAAU,SAAS,EAAG,CAAC,EAAI,EAAE,CACvE,EAAK,EAAO,EAAkB,CAAC,GAAG,EAAW,GAAG,EAAK,CAAC,KAAK,IAAI,EAAI,KAAK,CACxE,EAAO,IAAI,EAAO,EAAU,CAG5B,IAAM,EAAgB,EAAY,IAAI,EAAM,CACxC,GAAiB,CAAC,GACpB,EAAY,IAAI,EAAO,EAAK,EAAO,eAAe,CAAC,CACnD,EAAK,EAAO,eAAgB,OAAO,EAC1B,CAAC,GAAiB,IAC3B,EAAK,EAAO,eAAgB,EAAY,IAAI,EAAM,CAAC,CACnD,EAAY,OAAO,EAAM,EAG3B,EAAiB,EAAM,EAInB,EAAQ,CACZ,KAAM,kBACN,MAAO,gBACR,CAEK,EAAoB,GAAuB,CAC/C,IAAM,EAAU,EAAY,QAAU,EAChC,EAAU,EAAO,IAAI,EAAM,CAEjC,GAAI,GAAS,YAAa,CAExB,IAAM,GADQ,OAAO,EAAK,EAAS,aAAa,CAAC,EAAI,GAC/B,EAAM,MAAM,OAC5B,EAAQ,EAAQ,EAAI,OAAS,QAC7B,GACJ,EAAU,EAAS,QAAQ,IAAQ,EAAI,EAAM,KAC5C,QAAQ,KAAM,GAAG,KAAK,IAAI,EAAM,GAAG,CAEtC,EAAK,EAAS,aAAc,EAAM,CAClC,EAAK,EAAS,aAAc,EAAM,CAClC,EAAK,EAAS,aAAc,EAAQ,EAAI,SAAW,KAAK,CAGnD,EAAY,OAAS,SAAW,GACnC,EAA2B,EAAO,EAAM,CAExC,aAAiB,sBACnB,EAAM,MAAM,YAAY,qBAAsB,OAAO,CACrD,EAAM,MAAM,YAAY,qBAAsB,GAAG,EAAM,aAAa,IAAI,GAItE,EAA6B,GAAU,EAAgB,IAAiB,CACxE,SAAS,gBAAkB,GAAO,EAAS,EAAK,EACnD,EAAiB,CAEd,EAAa,GAAgB,EAAG,aAAa,aAAa,GAAK,UAC/D,EAAe,GACnB,aAAc,aACd,aAAc,GACd,EAAE,aAAc,oBACf,EAAwB,OAAS,SAGpC,IAAa,EAAb,cAAoC,CAAU,CAC5C,mBAAoB,CAClB,EAAO,IAAI,KAAM,EAAE,CAAC,CACpB,EAAoB,KAAK,CAE3B,sBAAuB,CACrB,EAAO,OAAO,KAAK,GAIvB,EAAe,OAAO,WAAY,EAAe,CAEjD,EAAY,YAAe,CACzB,EAAG,SAAU,QAAS,EAAkB,EAAY,CACpD,EAAW,SAAU,EAAsB,CACzC,gBAAiB,CACf,aACA,aACA,SACA,KACA,QACA,EACD,CACD,WAAY,GACZ,UAAW,GACX,QAAS,GACV,CAAC,CACH,CAAC"}
1
+ {"version":3,"file":"field.js","names":[],"sources":["../../../src/field/field.ts"],"sourcesContent":["import {\n announce,\n attr,\n attrOrCSS,\n customElements,\n DSElement,\n debounce,\n isWindows,\n on,\n onHotReload,\n onMutation,\n QUICK_EVENT,\n useId,\n warn,\n} from '../utils/utils';\n\n// TODO: Document that Validation must be hidden with \"hidden\" attribute (or completely removed from DOM), not display: none\ndeclare global {\n interface HTMLElementTagNameMap {\n 'ds-field': DSFieldElement;\n }\n}\n\nconst ATTR_INVALID = 'aria-invalid';\nconst ATTR_DESCRIBEDBY = 'aria-describedby';\nconst ATTR_INDETERMINATE = 'data-indeterminate';\nconst COUNTER_DEBOUNCE = isWindows() ? 800 : 200; // Longer debounce on Windows due to NVDA performance\nconst COUNTS = new WeakMap<HTMLInputElement, Element>(); // Using WeakMap so removed inputs/counts does not cause memory leaks\nconst FIELDS = new Map<DSFieldElement, string[]>(); // Map of Field and its describedby IDs so we can identify the ones we add/remove\nconst VALIDATIONS = new WeakSet<HTMLInputElement>(); // Used to ensure we only take control of aria-invalid if the current is or has been a validation element\nconst WARNING_MULTIPLE_INPUTS = `Fields should only have one input element. Use <fieldset> to group multiple fields:`;\n\nconst handleFieldMutations = (_doc: Node, records: MutationRecord[] = []) => {\n for (const { target } of records) {\n const isFieldset = target instanceof HTMLFieldSetElement;\n for (const [field] of FIELDS)\n if (isFieldset ? target.contains(field) : field.contains(target))\n handleFieldMutation(field);\n }\n};\n\nconst handleFieldMutation = (field: DSFieldElement) => {\n const labels: HTMLLabelElement[] = [];\n const nextDescs: string[] = []; // Keep track of descriptions we are adding in this mutation\n const prevDescs = FIELDS.get(field) || []; // Retrieve previously managed IDs for this field\n let input: HTMLInputElement | undefined;\n let counter: Element | undefined;\n let hasValidation = false;\n let invalid = false;\n\n for (const el of field.getElementsByTagName('*')) {\n if (el instanceof HTMLLabelElement) labels.push(el);\n if ((el as HTMLElement).hidden) continue; // Skip hidden elements except labels\n if (isInputLike(el)) {\n if (input) warn(WARNING_MULTIPLE_INPUTS, field);\n else input = el; // Only register if visible input\n } else {\n const type = el.getAttribute('data-field'); // Using getAttribute instead of attr for best performance\n if (type === 'counter') counter = el;\n if (type === 'validation') {\n nextDescs.unshift(useId(el));\n hasValidation = true;\n invalid = invalid || isInvalid(el);\n } else if (type) nextDescs.push(useId(el)); // Adds both counter and descriptions\n }\n }\n\n if (!input) return; // Do not warn about missing input as virtual DOM libraries might give false positives\n if (counter) COUNTS.set(input, counter);\n for (const label of labels) attr(label, 'for', useId(input));\n\n const fieldsetValidation = field\n .closest('fieldset')\n ?.querySelector<HTMLElement>(':scope > [data-field=\"validation\"]');\n\n // Connect fieldset validation to inputs\n if (fieldsetValidation && !fieldsetValidation?.hidden) {\n hasValidation = true;\n invalid = invalid || isInvalid(fieldsetValidation);\n nextDescs.unshift(useId(fieldsetValidation));\n }\n\n // Add support for data-indeterminate attribute as this normally can only be set by javascript\n const indeterminate = attr(input, ATTR_INDETERMINATE);\n if (indeterminate) input.indeterminate = indeterminate === 'true';\n\n // Expand click area to ds-field if radio/checkbox\n const isBoolish = input.type === 'radio' || input.type === 'checkbox';\n if (isBoolish) attr(field, 'data-clickdelegatefor', useId(input));\n\n // Setup aria-describedby, but repsect existing ids in aria-describedby\n const describedby = attr(input, ATTR_DESCRIBEDBY)?.trim().split(/\\s+/);\n const keep = describedby?.filter((id) => !prevDescs.includes(id)) || []; // Find non-ds-field-managed aria-describedby IDs\n attr(input, ATTR_DESCRIBEDBY, [...nextDescs, ...keep].join(' ') || null);\n FIELDS.set(field, nextDescs);\n\n // Only manage aria-invalid when field has validation elements, and aria-invalid does not already exist\n const hadValidation = VALIDATIONS.has(input);\n if (hasValidation && !hadValidation && !input.hasAttribute(ATTR_INVALID)) {\n attr(input, ATTR_INVALID, 'true');\n VALIDATIONS.add(input);\n } else if (!hasValidation && hadValidation) {\n attr(input, ATTR_INVALID, null); // Remove aria-invalid\n VALIDATIONS.delete(input);\n }\n\n handleFieldInput(input); // Update counter and textarea sizing\n};\n\n// Used as fallback in tests when CSS is not loaded\nconst TEXTS = {\n over: '%d tegn for mye',\n under: '%d tegn igjen',\n};\n\nconst handleFieldInput = (e: Event | Element) => {\n const input = ((e as Event).target || e) as HTMLInputElement;\n const counter = COUNTS.get(input);\n\n if (counter?.isConnected) {\n const limit = Number(attr(counter, 'data-limit')) || 0;\n const count = limit - input.value.length;\n const state = count < 0 ? 'over' : 'under';\n const label = (\n attrOrCSS(counter, `data-${state}`) || TEXTS[state]\n )?.replace('%d', `${Math.abs(count)}`);\n\n attr(counter, 'data-label', label); // Using attribute to prevent hydation errors, not using aria-label to make axe tests happy\n attr(counter, 'data-state', state);\n attr(counter, 'data-color', count < 0 ? 'danger' : null);\n\n // Only update live region when user is actually typing\n if ((e as Event).type === 'input' && label)\n debouncedCounterLiveRegion(input, label); // Debounce live region to avoid NVDA interupting announcing typed text\n }\n if (input instanceof HTMLTextAreaElement) {\n input.style.setProperty('--_ds-field-sizing', 'auto');\n input.style.setProperty('--_ds-field-sizing', `${input.scrollHeight}px`);\n }\n};\n\nconst debouncedCounterLiveRegion = debounce((input: Element, text: string) => {\n if (document.activeElement === input) announce(text); // Only announce if input is still focused\n}, COUNTER_DEBOUNCE);\n\nconst isInvalid = (el: Element) => el.getAttribute('data-color') !== 'success';\nconst isInputLike = (el: unknown): el is HTMLInputElement =>\n el instanceof HTMLElement &&\n 'validity' in el && // Adds support for custom elements implemeted with attachInternals()\n !(el instanceof HTMLButtonElement) && // But skip <button> elements\n (el as HTMLInputElement).type !== 'hidden'; // And skip input type=\"hidden\"\n\n// Custom element is used to performantly keep track of fields on the page\nexport class DSFieldElement extends DSElement {\n connectedCallback() {\n FIELDS.set(this, []); // Register field\n handleFieldMutation(this); // Initial setup\n }\n disconnectedCallback() {\n FIELDS.delete(this);\n }\n}\n\ncustomElements.define('ds-field', DSFieldElement);\n\nonHotReload('field', () => [\n on(document, 'input', handleFieldInput, QUICK_EVENT),\n onMutation(document, handleFieldMutations, {\n attributeFilter: [\n 'data-field',\n 'data-limit',\n 'hidden', // Needed to check validation visibility\n 'id', // Needed to sync label \"for\" when ID of input/selec/textarea changes\n 'value', // Needed to detect changes in controlled React inputs as they do not trigger input events\n ATTR_INDETERMINATE,\n ],\n attributes: true,\n childList: true,\n subtree: true,\n }),\n]);\n"],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,38 +1,47 @@
1
- export * from '@u-elements/u-datalist';
2
- import { UHTMLComboboxElement } from '@u-elements/u-combobox';
3
- import * as UTabs from '@u-elements/u-tabs';
1
+ import { UHTMLComboboxElement } from "@u-elements/u-combobox";
2
+ import * as UTabs from "@u-elements/u-tabs";
3
+ export * from "@u-elements/u-datalist";
4
4
 
5
+ //#region src/popover/popover.d.ts
5
6
  declare global {
6
- interface GlobalEventHandlersEventMap {
7
- 'ds-toggle-source': CustomEvent<Element>;
8
- }
7
+ interface GlobalEventHandlersEventMap {
8
+ 'ds-toggle-source': CustomEvent<Element>;
9
+ }
9
10
  }
10
-
11
+ //#endregion
12
+ //#region src/tooltip/tooltip.d.ts
11
13
  /**
12
14
  * setTooltipElement
13
15
  * @description Allows setting a custom tooltip element. It does not need to, and should not, be injected to document.body, as we inject on hover to ensure React hydration works as expected.
14
16
  * @param el The HTMLElement to use as tooltip
15
17
  */
16
18
  declare const setTooltipElement: (el?: HTMLElement | null) => void;
17
-
19
+ //#endregion
20
+ //#region src/utils/utils.d.ts
18
21
  declare const DSElement: {
19
- new (): HTMLElement;
20
- prototype: HTMLElement;
22
+ new (): HTMLElement;
23
+ prototype: HTMLElement;
21
24
  };
22
25
  /**
23
26
  * warn
24
27
  * @description Utility to console.log, but can be silenced in production with window.dsWarnings = false;
25
28
  */
26
29
  declare global {
27
- interface Window {
28
- dsWarnings?: boolean;
29
- }
30
+ interface Window {
31
+ dsWarnings?: boolean;
32
+ }
30
33
  }
31
34
  declare global {
32
- interface Window {
33
- _dsHotReloadCleanup?: Map<string, Array<() => void>>;
34
- }
35
+ interface Window {
36
+ _dsHotReloadCleanup?: Map<string, Array<() => void>>;
37
+ }
35
38
  }
39
+ /**
40
+ * onHotReload
41
+ * @description Runs a callback when window is loaded in browser, and ensures cleanup when hot-reloading
42
+ * @param key The key to identify setup and corresponding cleanup
43
+ * @param callback The callback to run when the page is ready
44
+ */
36
45
  /**
37
46
  * MutationObserver wrapper with automatic cleanup
38
47
  * @return new MutaionObserver
@@ -43,106 +52,115 @@ declare const onMutation: <T extends Node>(el: T, callback: (el: T, records?: Mu
43
52
  * @return A generated unique ID
44
53
  */
45
54
  declare global {
46
- interface Window {
47
- dsUseId?: number;
48
- }
55
+ interface Window {
56
+ dsUseId?: number;
57
+ }
49
58
  }
50
-
59
+ //#endregion
60
+ //#region src/breadcrumbs/breadcrumbs.d.ts
51
61
  declare global {
52
- interface HTMLElementTagNameMap {
53
- 'ds-breadcrumbs': DSBreadcrumbsElement;
54
- }
62
+ interface HTMLElementTagNameMap {
63
+ 'ds-breadcrumbs': DSBreadcrumbsElement;
64
+ }
55
65
  }
56
66
  declare class DSBreadcrumbsElement extends DSElement {
57
- _items?: HTMLCollectionOf<HTMLAnchorElement>;
58
- _label: string | null;
59
- _unresize?: () => void;
60
- _unmutate?: () => void;
61
- static get observedAttributes(): string[];
62
- connectedCallback(): void;
63
- attributeChangedCallback(_name: string, _prev?: string, next?: string): void;
64
- disconnectedCallback(): void;
67
+ _items?: HTMLCollectionOf<HTMLAnchorElement>;
68
+ _label: string | null;
69
+ _unresize?: () => void;
70
+ _unmutate?: () => void;
71
+ static get observedAttributes(): string[];
72
+ connectedCallback(): void;
73
+ attributeChangedCallback(_name: string, _prev?: string, next?: string): void;
74
+ disconnectedCallback(): void;
65
75
  }
66
-
76
+ //#endregion
77
+ //#region src/error-summary/error-summary.d.ts
67
78
  declare global {
68
- interface HTMLElementTagNameMap {
69
- 'ds-error-summary': DSErrorSummaryElement;
70
- }
79
+ interface HTMLElementTagNameMap {
80
+ 'ds-error-summary': DSErrorSummaryElement;
81
+ }
71
82
  }
72
83
  declare class DSErrorSummaryElement extends DSElement {
73
- _unmutate?: () => void;
74
- connectedCallback(): void;
75
- handleEvent({ target }: Event): void;
76
- disconnectedCallback(): void;
84
+ _unmutate?: () => void;
85
+ connectedCallback(): void;
86
+ handleEvent({
87
+ target
88
+ }: Event): void;
89
+ disconnectedCallback(): void;
77
90
  }
78
-
91
+ //#endregion
92
+ //#region src/field/field.d.ts
79
93
  declare global {
80
- interface HTMLElementTagNameMap {
81
- 'ds-field': DSFieldElement;
82
- }
94
+ interface HTMLElementTagNameMap {
95
+ 'ds-field': DSFieldElement;
96
+ }
83
97
  }
84
98
  declare class DSFieldElement extends DSElement {
85
- connectedCallback(): void;
86
- disconnectedCallback(): void;
99
+ connectedCallback(): void;
100
+ disconnectedCallback(): void;
87
101
  }
88
-
102
+ //#endregion
103
+ //#region src/pagination/pagination.d.ts
89
104
  declare global {
90
- interface HTMLElementTagNameMap {
91
- 'ds-pagination': DSPaginationElement;
92
- }
105
+ interface HTMLElementTagNameMap {
106
+ 'ds-pagination': DSPaginationElement;
107
+ }
93
108
  }
94
- declare const pagination: ({ current, total, show }: {
95
- current?: number | undefined;
96
- total?: number | undefined;
97
- show?: number | undefined;
109
+ declare const pagination: ({
110
+ current,
111
+ total,
112
+ show
113
+ }: {
114
+ current?: number | undefined;
115
+ total?: number | undefined;
116
+ show?: number | undefined;
98
117
  }) => {
99
- prev: number;
100
- next: number;
101
- pages: {
102
- current: false | "page";
103
- key: string;
104
- page: number;
105
- }[];
118
+ prev: number;
119
+ next: number;
120
+ pages: {
121
+ current: false | "page";
122
+ key: string;
123
+ page: number;
124
+ }[];
106
125
  };
107
126
  declare class DSPaginationElement extends DSElement {
108
- _unmutate?: () => void;
109
- _render?: () => void;
110
- static get observedAttributes(): string[];
111
- connectedCallback(): void;
112
- attributeChangedCallback(): void;
113
- disconnectedCallback(): void;
127
+ _unmutate?: () => void;
128
+ _render?: () => void;
129
+ static get observedAttributes(): string[];
130
+ connectedCallback(): void;
131
+ attributeChangedCallback(): void;
132
+ disconnectedCallback(): void;
114
133
  }
115
-
134
+ //#endregion
135
+ //#region src/suggestion/suggestion.d.ts
116
136
  declare global {
117
- interface HTMLElementTagNameMap {
118
- 'ds-suggestion': DSSuggestionElement;
119
- }
137
+ interface HTMLElementTagNameMap {
138
+ 'ds-suggestion': DSSuggestionElement;
139
+ }
120
140
  }
121
141
  declare class DSSuggestionElement extends UHTMLComboboxElement {
122
- _render?: () => void;
123
- _unmutate?: ReturnType<typeof onMutation>;
124
- connectedCallback(): void;
125
- disconnectedCallback(): void;
142
+ _render?: () => void;
143
+ _unmutate?: ReturnType<typeof onMutation>;
144
+ connectedCallback(): void;
145
+ disconnectedCallback(): void;
126
146
  }
127
-
147
+ //#endregion
148
+ //#region src/tabs/tabs.d.ts
128
149
  declare global {
129
- interface HTMLElementTagNameMap {
130
- 'ds-tabs': DSTabsElement;
131
- 'ds-tablist': DSTabListElement;
132
- 'ds-tab': DSTabElement;
133
- 'ds-tabpanel': DSTabPanelElement;
134
- }
135
- }
136
- declare class DSTabsElement extends UTabs.UHTMLTabsElement {
137
- }
138
- declare class DSTabListElement extends UTabs.UHTMLTabListElement {
139
- }
140
- declare class DSTabElement extends UTabs.UHTMLTabElement {
141
- }
142
- declare class DSTabPanelElement extends UTabs.UHTMLTabPanelElement {
150
+ interface HTMLElementTagNameMap {
151
+ 'ds-tabs': DSTabsElement;
152
+ 'ds-tablist': DSTabListElement;
153
+ 'ds-tab': DSTabElement;
154
+ 'ds-tabpanel': DSTabPanelElement;
155
+ }
143
156
  }
144
-
157
+ declare class DSTabsElement extends UTabs.UHTMLTabsElement {}
158
+ declare class DSTabListElement extends UTabs.UHTMLTabListElement {}
159
+ declare class DSTabElement extends UTabs.UHTMLTabElement {}
160
+ declare class DSTabPanelElement extends UTabs.UHTMLTabPanelElement {}
161
+ //#endregion
145
162
  export { DSBreadcrumbsElement, DSErrorSummaryElement, DSFieldElement, DSPaginationElement, DSSuggestionElement, DSTabElement, DSTabListElement, DSTabPanelElement, DSTabsElement, pagination, setTooltipElement };
163
+ //# sourceMappingURL=index.d.ts.map
146
164
  import type * as PreactTypes from 'preact'
147
165
  import type * as ReactTypes from 'react'
148
166
  import type * as SvelteTypes from 'svelte/elements'
@@ -331,4 +349,4 @@ declare module 'solid-js' {
331
349
  interface IntrinsicElements { 'ds-tabpanel': SolidDstabpanel }
332
350
  interface CustomEvents { }
333
351
  }
334
- }
352
+ }
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../src/popover/popover.ts","../src/tooltip/tooltip.ts","../src/utils/utils.ts","../src/breadcrumbs/breadcrumbs.ts","../src/error-summary/error-summary.ts","../src/field/field.ts","../src/pagination/pagination.ts","../src/suggestion/suggestion.ts","../src/tabs/tabs.ts"],"mappings":";;;;;QAYQ,MAAA;EAAA,UACI,2BAAA;IACR,kBAAA,EAAoB,WAAA,CAAY,OAAA;EAAA;AAAA;;;;;;;;cCsBvB,iBAAA,GAAqB,EAAA,GAAK,WAAA;;;cCxB1B,SAAA;EAAA,QAGI,WAAA;aAAA,WAAA;AAAA;;;;;QAkBT,MAAA;EAAA,UACI,MAAA;IACR,UAAA;EAAA;AAAA;AAAA,QAqFI,MAAA;EAAA,UACI,MAAA;IACR,mBAAA,GAAsB,GAAA,SAAY,KAAA;EAAA;AAAA;;;;;;;;;;;cAsBzB,UAAA,aAAwB,IAAA,EACnC,EAAA,EAAI,CAAA,EACJ,QAAA,GAAW,EAAA,EAAI,CAAA,EAAG,OAAA,GAAU,cAAA,aAC5B,OAAA,EAAS,oBAAA;;;;;QA8CH,MAAA;EAAA,UACI,MAAA;IACR,OAAA;EAAA;AAAA;;;QCzLI,MAAA;EAAA,UACI,qBAAA;IACR,gBAAA,EAAkB,oBAAA;EAAA;AAAA;AAAA,cAMT,oBAAA,SAA6B,SAAA;EACxC,MAAA,GAAS,gBAAA,CAAiB,iBAAA;EAC1B,MAAA;EACA,SAAA;EACA,SAAA;EAAA,WAEW,kBAAA,CAAA;EAGX,iBAAA,CAAA;EAUA,wBAAA,CAAyB,KAAA,UAAe,KAAA,WAAgB,IAAA;EAKxD,oBAAA,CAAA;AAAA;;;QC/BM,MAAA;EAAA,UACI,qBAAA;IACR,kBAAA,EAAoB,qBAAA;EAAA;AAAA;AAAA,cAIX,qBAAA,SAA8B,SAAA;EACzC,SAAA;EAEA,iBAAA,CAAA;EASA,WAAA,CAAA;IAAc;EAAA,GAAU,KAAA;EAGxB,oBAAA,CAAA;AAAA;;;QCfM,MAAA;EAAA,UACI,qBAAA;IACR,UAAA,EAAY,cAAA;EAAA;AAAA;AAAA,cAsIH,cAAA,SAAuB,SAAA;EAClC,iBAAA,CAAA;EAIA,oBAAA,CAAA;AAAA;;;QCrJM,MAAA;EAAA,UACI,qBAAA;IACR,eAAA,EAAiB,mBAAA;EAAA;AAAA;AAAA,cAUR,UAAA;EAAc,OAAA;EAAA,KAAA;EAAA;AAAA;;;;;;;;;;;;;cAUd,mBAAA,SAA4B,SAAA;EACvC,SAAA;EACA,OAAA;EAAA,WAEW,kBAAA,CAAA;EAGX,iBAAA,CAAA;EAcA,wBAAA,CAAA;EAGA,oBAAA,CAAA;AAAA;;;QC5CM,MAAA;EAAA,UACI,qBAAA;IACR,eAAA,EAAiB,mBAAA;EAAA;AAAA;AAAA,cAIR,mBAAA,SAA4B,oBAAA;EACvC,OAAA;EACA,SAAA,GAAY,UAAA,QAAkB,UAAA;EAE9B,iBAAA,CAAA;EAKA,oBAAA,CAAA;AAAA;;;QCvBM,MAAA;EAAA,UACI,qBAAA;IACR,SAAA,EAAW,aAAA;IACX,YAAA,EAAc,gBAAA;IACd,QAAA,EAAU,YAAA;IACV,aAAA,EAAe,iBAAA;EAAA;AAAA;AAAA,cAIN,aAAA,SAAsB,KAAA,CAAM,gBAAA;AAAA,cAC5B,gBAAA,SAAyB,KAAA,CAAM,mBAAA;AAAA,cAC/B,YAAA,SAAqB,KAAA,CAAM,eAAA;AAAA,cAC3B,iBAAA,SAA0B,KAAA,CAAM,oBAAA"}