diff --git a/.changeset/breezy-bananas-cross.md b/.changeset/breezy-bananas-cross.md new file mode 100644 index 000000000..40e2b15bb --- /dev/null +++ b/.changeset/breezy-bananas-cross.md @@ -0,0 +1,5 @@ +--- +'svelte-ux': minor +--- + +Cleanup a11y and TS warnings/errors diff --git a/.changeset/healthy-seas-bathe.md b/.changeset/healthy-seas-bathe.md new file mode 100644 index 000000000..b95975bbf --- /dev/null +++ b/.changeset/healthy-seas-bathe.md @@ -0,0 +1,5 @@ +--- +'svelte-ux': minor +--- + +[ButtonGroup] Remove mouse/keyboard event handlers (a11y). Use wrapping container to stop event propagation diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6d68438a7..4a14ecc45 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -27,6 +27,8 @@ jobs: - run: pnpm install --frozen-lockfile + - run: pnpm check + - run: pnpm lint - run: pnpm test:unit diff --git a/package.json b/package.json index 00c376d43..7b61ae9ba 100644 --- a/package.json +++ b/package.json @@ -7,6 +7,7 @@ "scripts": { "test:unit": "pnpm -r test:unit", "build": "rimraf packages/*/dist && pnpm -r build", + "check": "pnpm -r check", "lint": "pnpm -r lint", "format": "pnpm -r format", "changeset": "changeset", diff --git a/packages/svelte-ux/src/app.d.ts b/packages/svelte-ux/src/app.d.ts index 1cea0dcf2..911f8b6a0 100644 --- a/packages/svelte-ux/src/app.d.ts +++ b/packages/svelte-ux/src/app.d.ts @@ -4,6 +4,22 @@ declare namespace App { // interface Error {} // interface Locals {} - // interface PageData {} + + interface PageData { + meta: { + title?: string; + description?: string; + source?: string; + pageSource?: string; + api?: SveldJson; + features?: string[]; + related?: string[]; + hideUsage?: boolean; + hideTableOfContents?: boolean; + status?: string; + }; + } + + // interface PageState {} // interface Platform {} } diff --git a/packages/svelte-ux/src/docs/Link.svelte b/packages/svelte-ux/src/docs/Link.svelte index eec570e72..e607ded31 100644 --- a/packages/svelte-ux/src/docs/Link.svelte +++ b/packages/svelte-ux/src/docs/Link.svelte @@ -1,3 +1,5 @@ + + diff --git a/packages/svelte-ux/src/docs/ViewSourceButton.svelte b/packages/svelte-ux/src/docs/ViewSourceButton.svelte index 7a2f2948d..0a740c946 100644 --- a/packages/svelte-ux/src/docs/ViewSourceButton.svelte +++ b/packages/svelte-ux/src/docs/ViewSourceButton.svelte @@ -1,5 +1,7 @@ {#if source} diff --git a/packages/svelte-ux/src/lib/actions/_domTracker.ts b/packages/svelte-ux/src/lib/actions/_domTracker.ts index c007b9617..6584d07e2 100644 --- a/packages/svelte-ux/src/lib/actions/_domTracker.ts +++ b/packages/svelte-ux/src/lib/actions/_domTracker.ts @@ -51,10 +51,10 @@ export default class DomTracker { const existingAction = this.changes.actions.get(action.name); if (existingAction) { // Action already created, call action's update() (if available) - existingAction.update?.(options); + existingAction.update?.(options as any); } else { // Add new action - this.changes.actions.set(action.name, action(this.node, options)); + this.changes.actions.set(action.name, action(this.node, options as any)); } } diff --git a/packages/svelte-ux/src/lib/actions/dataBackground.ts b/packages/svelte-ux/src/lib/actions/dataBackground.ts index 23b5e8012..5bac6feef 100644 --- a/packages/svelte-ux/src/lib/actions/dataBackground.ts +++ b/packages/svelte-ux/src/lib/actions/dataBackground.ts @@ -28,7 +28,7 @@ export type DataBackgroundOptions = { */ baseline?: boolean; - tweened?: Parameters[1]; + tweened?: Parameters>[1]; }; export const dataBackground: Action = (node, options) => { diff --git a/packages/svelte-ux/src/lib/actions/mouse.ts b/packages/svelte-ux/src/lib/actions/mouse.ts index e8f00ff05..fa0dd7367 100644 --- a/packages/svelte-ux/src/lib/actions/mouse.ts +++ b/packages/svelte-ux/src/lib/actions/mouse.ts @@ -76,7 +76,7 @@ type MovableOptions = { /** * Track mouse position changes from mouse down on node to mouse up */ -export const movable: Action = (node, options = {}) => { +export const movable: Action = (node, options = {}) => { let lastX = 0; let lastY = 0; @@ -184,7 +184,7 @@ type MouseCoordsOptions = { }; /** Set relative mouse coordinates as --x/--y CSS variables */ -export const mouseCoords: Action = (node, target = node) => { +export const mouseCoords: Action = (node, target = node) => { function onMouseMove(e: MouseEvent) { // Mouse coordinates relative to node instead of viewport (`e.offsetX/Y` changes based on target/children) const rect = node.getBoundingClientRect(); @@ -209,7 +209,7 @@ export const mouseCoords: Action = (node, target = nod node.addEventListener('mouseleave', onMouseLeave); return { - update(target: HTMLElement) { + update(target: HTMLElement | undefined) { target = target; }, destroy() { diff --git a/packages/svelte-ux/src/lib/actions/observable.d.ts b/packages/svelte-ux/src/lib/actions/observable.d.ts deleted file mode 100644 index 2d30e674b..000000000 --- a/packages/svelte-ux/src/lib/actions/observable.d.ts +++ /dev/null @@ -1,7 +0,0 @@ -// https://github.com/sveltejs/language-tools/blob/master/docs/preprocessors/typescript.md -declare namespace svelteHTML { - interface HTMLAttributes { - 'on:intersecting'?: (event: CustomEvent) => any; - 'on:mutate'?: (event: CustomEvent) => any; - } -} diff --git a/packages/svelte-ux/src/lib/actions/observer.ts b/packages/svelte-ux/src/lib/actions/observer.ts index 391344250..12d110b9e 100644 --- a/packages/svelte-ux/src/lib/actions/observer.ts +++ b/packages/svelte-ux/src/lib/actions/observer.ts @@ -15,7 +15,10 @@ export const resize: Action = (node) => { }; }; -export const intersection: Action = (node, options) => { +export const intersection: Action = ( + node, + options = {} +) => { // TODO: Support defininting `options.root = node.parentNode` easily (maybe querySelector() string?) let observer = new IntersectionObserver( diff --git a/packages/svelte-ux/src/lib/actions/popover.ts b/packages/svelte-ux/src/lib/actions/popover.ts index 6a0b8f798..6efeb5f74 100644 --- a/packages/svelte-ux/src/lib/actions/popover.ts +++ b/packages/svelte-ux/src/lib/actions/popover.ts @@ -16,7 +16,7 @@ import { import { portal } from './portal.js'; export type PopoverOptions = { - anchorEl?: HTMLElement; + anchorEl?: Element | HTMLElement; placement?: Placement; offset?: OffsetOptions; padding?: number; @@ -71,7 +71,7 @@ export const popover: Action = (node, opt left: `${x}px`, top: `${y}px`, ...(options?.matchWidth && { - width: `${anchorEl.offsetWidth}px`, + width: `${(anchorEl as HTMLElement).offsetWidth}px`, }), }); }); diff --git a/packages/svelte-ux/src/lib/actions/scroll.ts b/packages/svelte-ux/src/lib/actions/scroll.ts index ceca27f55..e5c6f4687 100644 --- a/packages/svelte-ux/src/lib/actions/scroll.ts +++ b/packages/svelte-ux/src/lib/actions/scroll.ts @@ -33,20 +33,12 @@ export const scrollIntoView: Action +>; export const scrollShadow: Action = ( node, diff --git a/packages/svelte-ux/src/lib/actions/spotlight.ts b/packages/svelte-ux/src/lib/actions/spotlight.ts index 60306f55e..9038e71e2 100644 --- a/packages/svelte-ux/src/lib/actions/spotlight.ts +++ b/packages/svelte-ux/src/lib/actions/spotlight.ts @@ -49,20 +49,25 @@ export const spotlight: Action = (node, options) 'relative', 'isolate', - options?.radius && '[--spotlight-radius:var(--default-spotlight-radius)]', - options?.borderWidth && '[--spotlight-border-width:var(--default-spotlight-border-width)]', - options?.borderColorStops && - '[--spotlight-border-color-stops:var(--default-spotlight-border-color-stops)]', - options?.surfaceColorStops && - '[--spotlight-surface-color-stops:var(--default-spotlight-surface-color-stops)]', + options?.radius ? '[--spotlight-radius:var(--default-spotlight-radius)]' : '', + options?.borderWidth ? '[--spotlight-border-width:var(--default-spotlight-border-width)]' : '', + options?.borderColorStops + ? '[--spotlight-border-color-stops:var(--default-spotlight-border-color-stops)]' + : '', + options?.surfaceColorStops + ? '[--spotlight-surface-color-stops:var(--default-spotlight-surface-color-stops)]' + : '', - options?.hover?.radius && 'hover:[--spotlight-radius:var(--hover-spotlight-radius)]', - options?.hover?.borderWidth && - 'hover:[--spotlight-border-width:var(--hover-spotlight-border-width)]', - options?.hover?.borderColorStops && - 'hover:[--spotlight-border-color-stops:var(--hover-spotlight-border-color-stops)]', - options?.hover?.surfaceColorStops && - 'hover:[--spotlight-surface-color-stops:var(--hover-spotlight-surface-color-stops)]', + options?.hover?.radius ? 'hover:[--spotlight-radius:var(--hover-spotlight-radius)]' : '', + options?.hover?.borderWidth + ? 'hover:[--spotlight-border-width:var(--hover-spotlight-border-width)]' + : '', + options?.hover?.borderColorStops + ? 'hover:[--spotlight-border-color-stops:var(--hover-spotlight-border-color-stops)]' + : '', + options?.hover?.surfaceColorStops + ? 'hover:[--spotlight-surface-color-stops:var(--hover-spotlight-surface-color-stops)]' + : '', // Spotlight applied as :after element with 2 background gradients. padding-box for surface, and border-box for border 'before:absolute', diff --git a/packages/svelte-ux/src/lib/actions/table.ts b/packages/svelte-ux/src/lib/actions/table.ts index f5222fe75..6824b5393 100644 --- a/packages/svelte-ux/src/lib/actions/table.ts +++ b/packages/svelte-ux/src/lib/actions/table.ts @@ -150,6 +150,7 @@ export const tableCell: Action = (node, options) if (column.dataBackground) { const extents = extent(tableData ?? [], (d) => getCellValue(column, d)); + // @ts-ignore tracker.addAction(dataBackground, { value: context.cellValue, domain: tableData ? [min([0, extents[0]]), max([0, extents[1]])] : undefined, @@ -174,7 +175,11 @@ export const tableCell: Action = (node, options) }; }; -function getClasses(classProp: ColumnDef['classes']['td'], context: ResolveContext): string[] { +function getClasses( + // @ts-ignore + classProp: ColumnDef['classes']['td'], + context: ResolveContext +): string[] { const resolvedClassProp = typeof classProp === 'function' ? classProp(context) : classProp; if (typeof resolvedClassProp === 'string') { @@ -188,6 +193,7 @@ function getClasses(classProp: ColumnDef['classes']['td'], context: ResolveConte } function getStyleProperties( + // @ts-ignore styleProp: ColumnDef['style']['td'], context: ResolveContext ): string[][] { diff --git a/packages/svelte-ux/src/lib/actions/types.d.ts b/packages/svelte-ux/src/lib/actions/types.d.ts new file mode 100644 index 000000000..5c7a1ff77 --- /dev/null +++ b/packages/svelte-ux/src/lib/actions/types.d.ts @@ -0,0 +1,24 @@ +// https://github.com/sveltejs/language-tools/blob/master/docs/preprocessors/typescript.md +declare namespace svelteHTML { + interface HTMLAttributes { + // use:intersection + 'on:intersecting'?: (event: CustomEvent) => void; + + // use:mutate + 'on:mutate'?: (event: CustomEvent) => void; + + // use:movable + 'on:movestart'?: (event: CustomEvent<{ x: number; y: number }>) => void; + 'on:move'?: (event: CustomEvent<{ x: number; y: number; dx: number; dy: number }>) => void; + 'on:moveend'?: (event: CustomEvent<{ x: number; y: number }>) => void; + + // use:popover + 'on:clickOutside'?: (event: CustomEvent) => void; + + // use:overflow + 'on:overflow'?: (event: CustomEvent<{ overflowX: number; overflowY: number }>) => void; + + // use:longpress + 'on:longpress'?: (event: CustomEvent) => void; + } +} diff --git a/packages/svelte-ux/src/lib/components/ApiDocs.d.ts b/packages/svelte-ux/src/lib/components/ApiDocs.d.ts index 841973850..2a27f7a20 100644 --- a/packages/svelte-ux/src/lib/components/ApiDocs.d.ts +++ b/packages/svelte-ux/src/lib/components/ApiDocs.d.ts @@ -1,61 +1,61 @@ +// See: https://github.com/carbon-design-system/sveld/blob/main/src/ComponentParser.ts#L26 // See: https://github.com/mattjennings/vite-plugin-sveld/blob/main/types.d.ts interface SveldProp { name: string; - kind: string; + kind: 'let' | 'const' | 'function'; + constant: boolean; type?: string; + value?: any; + description?: string; isFunction: boolean; isFunctionDeclaration: boolean; isRequired: boolean; - constant: boolean; reactive: boolean; } interface SveldSlot { - name: string; + name?: string; default: boolean; - fallback: string; - slot_props: string; + fallback?: string; + slot_props?: string; description?: string; } -interface SveldEvent { - type: string; +interface ForwardedEvent { + type: 'forwarded'; name: string; - element: string; + element: ComponentInlineElement | ComponentElement; +} + +interface DispatchedEvent { + type: 'dispatched'; + name: string; + detail?: any; description?: string; } +type SvelteEvent = ForwardedEvent | DispatchedEvent; + interface SveldRestProps { - type: string; + type: 'InlineComponent' | 'Element'; name: string; } interface SveldTypedefs { type: string; name: string; + description?: string; ts: string; } -interface SveldModuleExport { - name: string; - kind: string; - type?: string; - value: string; - isFunction: boolean; - isFunctionDeclaration: boolean; - isRequired: boolean; - constant: boolean; - reactive: boolean; -} - interface SveldJson { props: SveldProp[]; slots: SveldSlot[]; events: SveldEvent[]; typedefs: SveldTypedefs[]; - rest_props: SveldRestProps[]; - moduleExports: SveldModuleExport[]; + rest_props: SveldRestProps; + moduleExports: SveldProp[]; componentComment?: string; extends?: { interface: string; diff --git a/packages/svelte-ux/src/lib/components/ApiDocs.svelte b/packages/svelte-ux/src/lib/components/ApiDocs.svelte index 7e3151ac9..7949673f8 100644 --- a/packages/svelte-ux/src/lib/components/ApiDocs.svelte +++ b/packages/svelte-ux/src/lib/components/ApiDocs.svelte @@ -133,7 +133,7 @@
{#if slot.slot_props != '{}'} - {#each parseSlotProps(slot.slot_props) as { key, value }} + {#each parseSlotProps(slot.slot_props ?? '') as { key, value }}
diff --git a/packages/svelte-ux/src/lib/components/Breadcrumb.svelte b/packages/svelte-ux/src/lib/components/Breadcrumb.svelte index c30e7afb5..a5f611758 100644 --- a/packages/svelte-ux/src/lib/components/Breadcrumb.svelte +++ b/packages/svelte-ux/src/lib/components/Breadcrumb.svelte @@ -1,11 +1,11 @@ - -
+
diff --git a/packages/svelte-ux/src/lib/components/Checkbox.svelte b/packages/svelte-ux/src/lib/components/Checkbox.svelte index f051c616b..d0facda69 100644 --- a/packages/svelte-ux/src/lib/components/Checkbox.svelte +++ b/packages/svelte-ux/src/lib/components/Checkbox.svelte @@ -32,7 +32,7 @@ groupCheck(); } function groupCheck() { - checked = group.includes(value); + checked = group?.includes(value) ?? false; } // Update group when checkbox changes diff --git a/packages/svelte-ux/src/lib/components/Code.svelte b/packages/svelte-ux/src/lib/components/Code.svelte index ff3090585..ddaa6105a 100644 --- a/packages/svelte-ux/src/lib/components/Code.svelte +++ b/packages/svelte-ux/src/lib/components/Code.svelte @@ -3,7 +3,6 @@ import 'prism-svelte'; import { cls } from '../utils/styles.js'; - import { getComponentClasses } from './theme.js'; import CopyButton from './CopyButton.svelte'; export let source: string | null = null; @@ -17,11 +16,9 @@ pre?: string; code?: string; } = {}; - - const settingsClasses = getComponentClasses('Code'); -
+
{#if source}
 isSame(date, d))
         : selected instanceof Object
-          ? isSame(date, selected.from ?? selected.to)
+          ? // @ts-ignore
+            isSame(date, selected.from ?? selected.to)
           : false;
 
   $: isSelectedEnd =
@@ -66,7 +72,8 @@
       : selected instanceof Array
         ? selected.some((d) => isSame(date, d))
         : selected instanceof Object
-          ? isSame(date, selected.to ?? selected.from)
+          ? // @ts-ignore
+            isSame(date, selected.to ?? selected.from)
           : false;
 
   $: isCurrent = isSame(date, new Date());
diff --git a/packages/svelte-ux/src/lib/components/DateSelect.svelte b/packages/svelte-ux/src/lib/components/DateSelect.svelte
index 718283d5d..e3204a059 100644
--- a/packages/svelte-ux/src/lib/components/DateSelect.svelte
+++ b/packages/svelte-ux/src/lib/components/DateSelect.svelte
@@ -20,6 +20,7 @@
    */
   export let disabledDates: DisabledDate | undefined = undefined;
 
+  // @ts-ignore
   $: startOfMonth = selected?.[activeDate] ? startOfMonthFunc(selected[activeDate]) : undefined;
 
 
diff --git a/packages/svelte-ux/src/lib/components/Dialog.svelte b/packages/svelte-ux/src/lib/components/Dialog.svelte
index bda043c84..33c2e7073 100644
--- a/packages/svelte-ux/src/lib/components/Dialog.svelte
+++ b/packages/svelte-ux/src/lib/components/Dialog.svelte
@@ -106,6 +106,7 @@
       }
     }}
     use:portalAction={portal}
+    role="presentation"
   >