@flightlesslabs/dodo-ui 0.17.2 → 0.18.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/index.d.ts CHANGED
@@ -3,6 +3,7 @@ export type { ComponentRoundness } from './types/roundness.js';
3
3
  export type { ComponentSize } from './types/size.js';
4
4
  export type { ComponentWeight } from './types/weight.js';
5
5
  export type { PositionY, PositionX } from './types/position.js';
6
+ export type { DropdownArrowPosition } from './types/special.js';
6
7
  /** developer tools: helpers: logger */
7
8
  export { default as createLogger } from './stories/developer tools/helpers/logger/logger.js';
8
9
  export type { LogLevel, LoggerOptions, } from './stories/developer tools/helpers/logger/logger.js';
@@ -50,7 +51,7 @@ export { default as Message } from './stories/components/Form/Message/Message.sv
50
51
  export type { MessageProps } from './stories/components/Form/Message/Message.svelte';
51
52
  /** Form: Select */
52
53
  export { default as Select } from './stories/components/Form/Select/Select.svelte';
53
- export type { SelectOption, SelectDropdownArrowPosition, SelectProps, } from './stories/components/Form/Select/Select.svelte';
54
+ export type { SelectOption, SelectProps } from './stories/components/Form/Select/Select.svelte';
54
55
  /** Form: NumericInput */
55
56
  export { default as NumericInput } from './stories/components/Form/NumericInput/NumericInput.svelte';
56
57
  export type { NumericInputProps } from './stories/components/Form/NumericInput/NumericInput.svelte';
@@ -89,6 +90,9 @@ export { default as Row } from './stories/components/Layout/Grid/Row/Row.svelte'
89
90
  export type { GridRowProps } from './stories/components/Layout/Grid/Row/Row.svelte';
90
91
  export { default as Column } from './stories/components/Layout/Grid/Column/Column.svelte';
91
92
  export type { GridColumnSize, GridColumnProps, } from './stories/components/Layout/Grid/Column/Column.svelte';
93
+ /** Layout: Accordian */
94
+ export { default as Accordian } from './stories/components/Layout/Accordian/Accordian.svelte';
95
+ export type { AccordianProps, AccordianToggleEvent, } from './stories/components/Layout/Accordian/Accordian.svelte';
92
96
  /** Info: Calendar */
93
97
  export { default as Calendar } from './stories/components/Info/Calendar/Calendar.svelte';
94
98
  export type { CalendarProps, CalendarActiveSection, } from './stories/components/Info/Calendar/Calendar.svelte';
package/dist/index.js CHANGED
@@ -55,6 +55,8 @@ export { default as DynamicMenu } from './stories/components/Layout/Menu/Dynamic
55
55
  export { default as Grid } from './stories/components/Layout/Grid/Grid.svelte';
56
56
  export { default as Row } from './stories/components/Layout/Grid/Row/Row.svelte';
57
57
  export { default as Column } from './stories/components/Layout/Grid/Column/Column.svelte';
58
+ /** Layout: Accordian */
59
+ export { default as Accordian } from './stories/components/Layout/Accordian/Accordian.svelte';
58
60
  /** Info: Calendar */
59
61
  export { default as Calendar } from './stories/components/Info/Calendar/Calendar.svelte';
60
62
  export { default as CalendarDatesChart } from './stories/components/Info/Calendar/SubComponents/CalendarDatesChart/CalendarDatesChart.svelte';
@@ -7,7 +7,6 @@ export type SelectOption = {
7
7
  label: string;
8
8
  disabled?: boolean;
9
9
  };
10
- export type SelectDropdownArrowPosition = false | 'before' | 'after';
11
10
  export interface SelectProps {
12
11
  /** How large should the button be? */
13
12
  size?: ComponentSize;
@@ -90,7 +89,7 @@ export interface SelectProps {
90
89
  /** Dropdown Arrow Icon */
91
90
  customDropdownArrowIcon?: (open: boolean) => Snippet;
92
91
  /** Select Dropdown Arrow Position */
93
- dropdownArrowPosition?: SelectDropdownArrowPosition;
92
+ dropdownArrowPosition?: DropdownArrowPosition;
94
93
  /** Popup stick horizontally */
95
94
  popupPositionX?: PositionX;
96
95
  /** Popup stick vertically */
@@ -103,6 +102,7 @@ export interface SelectProps {
103
102
  open?: boolean;
104
103
  }
105
104
  import { type MenuItemProps, type MenuProps, type PaperProps, type PopperProps, type PositionX, type PositionY } from '../../../../index.js';
105
+ import type { DropdownArrowPosition } from '../../../../types/special.js';
106
106
  declare const Select: import("svelte").Component<SelectProps, {}, "ref" | "open">;
107
107
  type Select = ReturnType<typeof Select>;
108
108
  export default Select;
@@ -0,0 +1,52 @@
1
+ <script module lang="ts">import { defineMeta } from '@storybook/addon-svelte-csf';
2
+ import Accordian from './Accordian.svelte';
3
+ import { componentSizeArray } from '../../../../types/size.js';
4
+ export const storyAccordianArgTypes = {
5
+ size: {
6
+ control: { type: 'select' },
7
+ options: componentSizeArray,
8
+ },
9
+ };
10
+ // More on how to set up stories at: https://storybook.js.org/docs/writing-stories
11
+ const { Story } = defineMeta({
12
+ component: Accordian,
13
+ tags: ['autodocs'],
14
+ argTypes: storyAccordianArgTypes,
15
+ });
16
+ </script>
17
+
18
+ <Story name="Default" asChild>
19
+ <Accordian>
20
+ {#snippet summary()}
21
+ Click me!
22
+ {/snippet}
23
+
24
+ Lorem ipsum dolor sit amet consectetur adipisicing elit. Consequuntur nisi hic accusamus,
25
+ mollitia velit corporis, sit culpa nam ducimus quisquam aliquam eos atque doloribus architecto
26
+ at harum, explicabo et doloremque.
27
+ </Accordian>
28
+ </Story>
29
+
30
+ <Story name="Open by Default" asChild>
31
+ <Accordian defaultOpen={true}>
32
+ {#snippet summary()}
33
+ Click me!
34
+ {/snippet}
35
+
36
+ Lorem ipsum dolor sit amet consectetur adipisicing elit. Consequuntur nisi hic accusamus,
37
+ mollitia velit corporis, sit culpa nam ducimus quisquam aliquam eos atque doloribus architecto
38
+ at harum, explicabo et doloremque.
39
+ </Accordian>
40
+ </Story>
41
+
42
+ <Story name="Full Width Summary" asChild>
43
+ <Accordian fullWidthSummary>
44
+ {#snippet summary()}
45
+ Click me!
46
+ {/snippet}
47
+
48
+ Lorem ipsum dolor sit amet consectetur adipisicing elit. Consequuntur nisi hic accusamus,
49
+ mollitia velit corporis, sit culpa nam ducimus quisquam aliquam eos atque doloribus architecto
50
+ at harum, explicabo et doloremque.
51
+ </Accordian>
52
+ </Story>
@@ -0,0 +1,21 @@
1
+ import Accordian from './Accordian.svelte';
2
+ import type { StoryBookArgTypes } from '../../../../storybook-types.js';
3
+ export declare const storyAccordianArgTypes: StoryBookArgTypes;
4
+ interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
5
+ new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
6
+ $$bindings?: Bindings;
7
+ } & Exports;
8
+ (internal: unknown, props: {
9
+ $$events?: Events;
10
+ $$slots?: Slots;
11
+ }): Exports & {
12
+ $set?: any;
13
+ $on?: any;
14
+ };
15
+ z_$$bindings?: Bindings;
16
+ }
17
+ declare const Accordian: $$__sveltets_2_IsomorphicComponent<Record<string, never>, {
18
+ [evt: string]: CustomEvent<any>;
19
+ }, {}, {}, string>;
20
+ type Accordian = InstanceType<typeof Accordian>;
21
+ export default Accordian;
@@ -0,0 +1,121 @@
1
+ <script lang="ts" module>import Icon from '@iconify/svelte';
2
+ import { onMount } from 'svelte';
3
+ </script>
4
+
5
+ <script lang="ts">"use strict";
6
+ let { class: className = '', ref = $bindable(), ontoggle, open = $bindable(), defaultOpen, summary, children, size = 'normal', fullWidthSummary = false, customDropdownArrowIcon: customDropdownArrowIconInternal, dropdownArrowPosition = 'before', } = $props();
7
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
8
+ let customDropdownArrowIconTyped = customDropdownArrowIconInternal;
9
+ let isUserInteraction = $state(false);
10
+ function ontoggleMod(e) {
11
+ if (isUserInteraction) {
12
+ if (ontoggle) {
13
+ ontoggle(e);
14
+ }
15
+ }
16
+ isUserInteraction = false;
17
+ }
18
+ function onsummaryclick() {
19
+ isUserInteraction = true;
20
+ }
21
+ onMount(() => {
22
+ if (open === true) {
23
+ ref.open = true;
24
+ }
25
+ else if (open === false) {
26
+ ref.open = false;
27
+ }
28
+ else if (defaultOpen === true) {
29
+ ref.open = true;
30
+ }
31
+ else if (defaultOpen === false) {
32
+ ref.open = false;
33
+ }
34
+ });
35
+ </script>
36
+
37
+ {#snippet dropdownArrowIcon()}
38
+ {#if customDropdownArrowIconTyped}
39
+ {@render customDropdownArrowIconTyped(open)}
40
+ {:else}
41
+ <div class="IconOpen">
42
+ <Icon icon="material-symbols:arrow-drop-up-rounded" width="32" height="32" />
43
+ </div>
44
+ <div class="IconClose">
45
+ <Icon icon="material-symbols:arrow-drop-down-rounded" width="32" height="32" />
46
+ </div>
47
+ {/if}
48
+ {/snippet}
49
+
50
+ <details
51
+ class:fullWidthSummary
52
+ class={['dodo-ui-Accordian', `size--${size}`, className].join(' ')}
53
+ bind:this={ref}
54
+ {open}
55
+ ontoggle={ontoggleMod}
56
+ >
57
+ {#if summary}
58
+ <summary onclick={onsummaryclick}>
59
+ {#if dropdownArrowPosition === 'before'}
60
+ <div class:open class="DropdownArrow before">
61
+ {@render dropdownArrowIcon()}
62
+ </div>
63
+ {/if}
64
+ {@render summary()}
65
+ {#if dropdownArrowPosition === 'after'}
66
+ <div class:open class="DropdownArrow after">
67
+ {@render dropdownArrowIcon()}
68
+ </div>
69
+ {/if}
70
+ </summary>
71
+ {/if}
72
+
73
+ {#if children}
74
+ <div class="AccordianContent">
75
+ {@render children()}
76
+ </div>
77
+ {/if}
78
+ </details>
79
+
80
+ <style>.dodo-ui-Accordian {
81
+ color: var(--dodo-color-neutral-900);
82
+ width: 100%;
83
+ }
84
+ .dodo-ui-Accordian summary {
85
+ display: inline-flex;
86
+ align-items: center;
87
+ cursor: pointer;
88
+ user-select: none;
89
+ font-weight: 500;
90
+ }
91
+ .dodo-ui-Accordian.fullWidthSummary summary {
92
+ display: flex;
93
+ width: 100%;
94
+ }
95
+ .dodo-ui-Accordian[open] .IconOpen {
96
+ display: flex;
97
+ }
98
+ .dodo-ui-Accordian[open] .IconClose {
99
+ display: none;
100
+ }
101
+ .dodo-ui-Accordian:not([open]) .IconOpen {
102
+ display: none;
103
+ }
104
+ .dodo-ui-Accordian:not([open]) .IconClose {
105
+ display: flex;
106
+ }
107
+ .dodo-ui-Accordian.size--normal summary {
108
+ font-size: 1rem;
109
+ min-height: var(--dodo-ui-element-height-normal);
110
+ }
111
+ .dodo-ui-Accordian.size--small summary {
112
+ font-size: 0.9rem;
113
+ min-height: var(--dodo-ui-element-height-small);
114
+ }
115
+ .dodo-ui-Accordian.size--large summary {
116
+ font-size: 1.1rem;
117
+ min-height: var(--dodo-ui-element-height-large);
118
+ }
119
+ .dodo-ui-Accordian .AccordianContent {
120
+ margin-top: var(--dodo-ui-space);
121
+ }</style>
@@ -0,0 +1,34 @@
1
+ import type { ComponentSize } from '../../../../types/size.js';
2
+ import type { DropdownArrowPosition } from '../../../../types/special.js';
3
+ import { type Snippet } from 'svelte';
4
+ import type { EventHandler } from 'svelte/elements';
5
+ export type AccordianToggleEvent = Event & {
6
+ currentTarget: EventTarget & HTMLDetailsElement;
7
+ };
8
+ export interface AccordianProps {
9
+ /** Contents goes here */
10
+ children?: Snippet;
11
+ /** Accordian summary */
12
+ summary?: Snippet;
13
+ /** summary full width */
14
+ fullWidthSummary?: boolean;
15
+ /** Accordian ref */
16
+ ref?: HTMLDetailsElement;
17
+ /** Custom css class */
18
+ class?: string;
19
+ /** The toggle event handler */
20
+ ontoggle?: EventHandler<Event, HTMLDetailsElement>;
21
+ /** Open state, for dynmaic Accordians */
22
+ open?: boolean;
23
+ /** default Open, for static Accordians */
24
+ defaultOpen?: boolean;
25
+ /** How large should the button be? */
26
+ size?: ComponentSize;
27
+ /** Select Dropdown Arrow Position */
28
+ dropdownArrowPosition?: DropdownArrowPosition;
29
+ /** Dropdown Arrow Icon */
30
+ customDropdownArrowIcon?: (open: boolean) => Snippet;
31
+ }
32
+ declare const Accordian: import("svelte").Component<AccordianProps, {}, "ref" | "open">;
33
+ type Accordian = ReturnType<typeof Accordian>;
34
+ export default Accordian;
@@ -0,0 +1,69 @@
1
+ <script module lang="ts">import { defineMeta } from '@storybook/addon-svelte-csf';
2
+ import Accordian from '../Accordian.svelte';
3
+ import { storyAccordianArgTypes } from '../Accordian.stories.svelte';
4
+ import Icon from '@iconify/svelte';
5
+ // More on how to set up stories at: https://storybook.js.org/docs/writing-stories
6
+ const { Story } = defineMeta({
7
+ component: Accordian,
8
+ tags: ['autodocs'],
9
+ argTypes: storyAccordianArgTypes,
10
+ });
11
+ let open = $state(true);
12
+ </script>
13
+
14
+ <Story name="DropdownArrowPositionBefore" asChild>
15
+ <Accordian>
16
+ {#snippet summary()}
17
+ Click me!
18
+ {/snippet}
19
+
20
+ Lorem ipsum dolor sit amet consectetur adipisicing elit. Consequuntur nisi hic accusamus,
21
+ mollitia velit corporis, sit culpa nam ducimus quisquam aliquam eos atque doloribus architecto
22
+ at harum, explicabo et doloremque.
23
+ </Accordian>
24
+ </Story>
25
+
26
+ <Story name="DropdownArrowPositionAfter" asChild>
27
+ <Accordian dropdownArrowPosition="after">
28
+ {#snippet summary()}
29
+ Click me!
30
+ {/snippet}
31
+
32
+ Lorem ipsum dolor sit amet consectetur adipisicing elit. Consequuntur nisi hic accusamus,
33
+ mollitia velit corporis, sit culpa nam ducimus quisquam aliquam eos atque doloribus architecto
34
+ at harum, explicabo et doloremque.
35
+ </Accordian>
36
+ </Story>
37
+
38
+ <Story name="HideDropdownArrow" asChild>
39
+ <Accordian dropdownArrowPosition={false}>
40
+ {#snippet summary()}
41
+ Click me!
42
+ {/snippet}
43
+
44
+ Lorem ipsum dolor sit amet consectetur adipisicing elit. Consequuntur nisi hic accusamus,
45
+ mollitia velit corporis, sit culpa nam ducimus quisquam aliquam eos atque doloribus architecto
46
+ at harum, explicabo et doloremque.
47
+ </Accordian>
48
+ </Story>
49
+
50
+ <!-- Format look and feel Dropdown Arrow icon -->
51
+ <Story name="CustomDropdownArrowIcon" asChild>
52
+ <Accordian {open} ontoggle={() => (open = !open)}>
53
+ {#snippet summary()}
54
+ Click me!
55
+ {/snippet}
56
+
57
+ Lorem ipsum dolor sit amet consectetur adipisicing elit. Consequuntur nisi hic accusamus,
58
+ mollitia velit corporis, sit culpa nam ducimus quisquam aliquam eos atque doloribus architecto
59
+ at harum, explicabo et doloremque.
60
+
61
+ {#snippet customDropdownArrowIcon(open)}
62
+ {#if open}
63
+ <Icon icon="mingcute:up-fill" width="24" height="24" />
64
+ {:else}
65
+ <Icon icon="mingcute:down-fill" width="24" height="24" />
66
+ {/if}
67
+ {/snippet}
68
+ </Accordian>
69
+ </Story>
@@ -0,0 +1,18 @@
1
+ interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
2
+ new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
3
+ $$bindings?: Bindings;
4
+ } & Exports;
5
+ (internal: unknown, props: {
6
+ $$events?: Events;
7
+ $$slots?: Slots;
8
+ }): Exports & {
9
+ $set?: any;
10
+ $on?: any;
11
+ };
12
+ z_$$bindings?: Bindings;
13
+ }
14
+ declare const Customize: $$__sveltets_2_IsomorphicComponent<Record<string, never>, {
15
+ [evt: string]: CustomEvent<any>;
16
+ }, {}, {}, string>;
17
+ type Customize = InstanceType<typeof Customize>;
18
+ export default Customize;
@@ -0,0 +1,30 @@
1
+ <script module lang="ts">import { defineMeta } from '@storybook/addon-svelte-csf';
2
+ import { storyAccordianArgTypes } from '../Accordian.stories.svelte';
3
+ import Accordian, {} from '../Accordian.svelte';
4
+ // More on how to set up stories at: https://storybook.js.org/docs/writing-stories
5
+ const { Story } = defineMeta({
6
+ component: Accordian,
7
+ tags: ['autodocs'],
8
+ argTypes: storyAccordianArgTypes,
9
+ });
10
+ let open = $state(false);
11
+ </script>
12
+
13
+ <Story name="Toggle" asChild>
14
+ <Accordian
15
+ {open}
16
+ ontoggle={(e: AccordianToggleEvent) => {
17
+ open = !open;
18
+
19
+ console.log('Input Event', e);
20
+ }}
21
+ >
22
+ {#snippet summary()}
23
+ Click me!
24
+ {/snippet}
25
+
26
+ Lorem ipsum dolor sit amet consectetur adipisicing elit. Consequuntur nisi hic accusamus,
27
+ mollitia velit corporis, sit culpa nam ducimus quisquam aliquam eos atque doloribus architecto
28
+ at harum, explicabo et doloremque.
29
+ </Accordian>
30
+ </Story>
@@ -0,0 +1,18 @@
1
+ interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
2
+ new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
3
+ $$bindings?: Bindings;
4
+ } & Exports;
5
+ (internal: unknown, props: {
6
+ $$events?: Events;
7
+ $$slots?: Slots;
8
+ }): Exports & {
9
+ $set?: any;
10
+ $on?: any;
11
+ };
12
+ z_$$bindings?: Bindings;
13
+ }
14
+ declare const Events: $$__sveltets_2_IsomorphicComponent<Record<string, never>, {
15
+ [evt: string]: CustomEvent<any>;
16
+ }, {}, {}, string>;
17
+ type Events = InstanceType<typeof Events>;
18
+ export default Events;
@@ -0,0 +1,48 @@
1
+ <script module>
2
+ import { defineMeta } from '@storybook/addon-svelte-csf';
3
+ import Accordian from '../Accordian.svelte';
4
+ import { storyAccordianArgTypes } from '../Accordian.stories.svelte';
5
+
6
+ // More on how to set up stories at: https://storybook.js.org/docs/writing-stories
7
+ const { Story } = defineMeta({
8
+ component: Accordian,
9
+ tags: ['autodocs'],
10
+ argTypes: storyAccordianArgTypes,
11
+ });
12
+ </script>
13
+
14
+ <Story name="Normal" asChild>
15
+ <Accordian>
16
+ {#snippet summary()}
17
+ Click me!
18
+ {/snippet}
19
+
20
+ Lorem ipsum dolor sit amet consectetur adipisicing elit. Consequuntur nisi hic accusamus,
21
+ mollitia velit corporis, sit culpa nam ducimus quisquam aliquam eos atque doloribus architecto
22
+ at harum, explicabo et doloremque.
23
+ </Accordian>
24
+ </Story>
25
+
26
+ <Story name="Small" asChild>
27
+ <Accordian size="small">
28
+ {#snippet summary()}
29
+ Click me!
30
+ {/snippet}
31
+
32
+ Lorem ipsum dolor sit amet consectetur adipisicing elit. Consequuntur nisi hic accusamus,
33
+ mollitia velit corporis, sit culpa nam ducimus quisquam aliquam eos atque doloribus architecto
34
+ at harum, explicabo et doloremque.
35
+ </Accordian>
36
+ </Story>
37
+
38
+ <Story name="Larger" asChild>
39
+ <Accordian size="large">
40
+ {#snippet summary()}
41
+ Click me!
42
+ {/snippet}
43
+
44
+ Lorem ipsum dolor sit amet consectetur adipisicing elit. Consequuntur nisi hic accusamus,
45
+ mollitia velit corporis, sit culpa nam ducimus quisquam aliquam eos atque doloribus architecto
46
+ at harum, explicabo et doloremque.
47
+ </Accordian>
48
+ </Story>
@@ -0,0 +1,26 @@
1
+ export default Size;
2
+ type Size = SvelteComponent<{
3
+ [x: string]: never;
4
+ }, {
5
+ [evt: string]: CustomEvent<any>;
6
+ }, {}> & {
7
+ $$bindings?: string | undefined;
8
+ };
9
+ declare const Size: $$__sveltets_2_IsomorphicComponent<{
10
+ [x: string]: never;
11
+ }, {
12
+ [evt: string]: CustomEvent<any>;
13
+ }, {}, {}, string>;
14
+ interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
15
+ new (options: import("svelte").ComponentConstructorOptions<Props>): import("svelte").SvelteComponent<Props, Events, Slots> & {
16
+ $$bindings?: Bindings;
17
+ } & Exports;
18
+ (internal: unknown, props: {
19
+ $$events?: Events;
20
+ $$slots?: Slots;
21
+ }): Exports & {
22
+ $set?: any;
23
+ $on?: any;
24
+ };
25
+ z_$$bindings?: Bindings;
26
+ }
@@ -0,0 +1 @@
1
+ export type DropdownArrowPosition = false | 'before' | 'after';
@@ -0,0 +1 @@
1
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flightlesslabs/dodo-ui",
3
- "version": "0.17.2",
3
+ "version": "0.18.0",
4
4
  "scripts": {
5
5
  "copy-css": "cpy src/lib/styles/global.css dist/styles --parents",
6
6
  "build": "vite build && pnpm copy-css && pnpm run prepack",
@@ -60,7 +60,7 @@
60
60
  "@storybook/addon-vitest": "^9.1.1",
61
61
  "@storybook/sveltekit": "^9.1.1",
62
62
  "@sveltejs/adapter-static": "^3.0.8",
63
- "@sveltejs/kit": "^2.27.0",
63
+ "@sveltejs/kit": "^2.27.1",
64
64
  "@sveltejs/package": "^2.4.0",
65
65
  "@sveltejs/vite-plugin-svelte": "^6.1.0",
66
66
  "@types/file-saver": "^2.0.7",
@@ -77,14 +77,14 @@
77
77
  "prettier": "^3.6.2",
78
78
  "prettier-plugin-svelte": "^3.4.0",
79
79
  "publint": "^0.3.12",
80
- "sass": "^1.89.2",
80
+ "sass": "^1.90.0",
81
81
  "storybook": "^9.1.1",
82
- "svelte": "^5.37.3",
82
+ "svelte": "^5.38.0",
83
83
  "svelte-check": "^4.3.1",
84
84
  "svelte-preprocess": "^6.0.3",
85
85
  "typescript": "^5.9.2",
86
86
  "typescript-eslint": "^8.39.0",
87
- "vite": "^7.0.6",
87
+ "vite": "^7.1.0",
88
88
  "vitest": "^3.2.4"
89
89
  },
90
90
  "keywords": [
package/src/lib/index.ts CHANGED
@@ -12,6 +12,8 @@ export type { ComponentWeight } from './types/weight.js';
12
12
 
13
13
  export type { PositionY, PositionX } from './types/position.js';
14
14
 
15
+ export type { DropdownArrowPosition } from './types/special.js';
16
+
15
17
  /** developer tools: helpers: logger */
16
18
  export { default as createLogger } from '$lib/stories/developer tools/helpers/logger/logger.js';
17
19
  export type {
@@ -103,11 +105,7 @@ export type { MessageProps } from '$lib/stories/components/Form/Message/Message.
103
105
 
104
106
  /** Form: Select */
105
107
  export { default as Select } from '$lib/stories/components/Form/Select/Select.svelte';
106
- export type {
107
- SelectOption,
108
- SelectDropdownArrowPosition,
109
- SelectProps,
110
- } from '$lib/stories/components/Form/Select/Select.svelte';
108
+ export type { SelectOption, SelectProps } from '$lib/stories/components/Form/Select/Select.svelte';
111
109
 
112
110
  /** Form: NumericInput */
113
111
  export { default as NumericInput } from '$lib/stories/components/Form/NumericInput/NumericInput.svelte';
@@ -172,6 +170,13 @@ export type {
172
170
  GridColumnProps,
173
171
  } from '$lib/stories/components/Layout/Grid/Column/Column.svelte';
174
172
 
173
+ /** Layout: Accordian */
174
+ export { default as Accordian } from '$lib/stories/components/Layout/Accordian/Accordian.svelte';
175
+ export type {
176
+ AccordianProps,
177
+ AccordianToggleEvent,
178
+ } from '$lib/stories/components/Layout/Accordian/Accordian.svelte';
179
+
175
180
  /** Info: Calendar */
176
181
  export { default as Calendar } from '$lib/stories/components/Info/Calendar/Calendar.svelte';
177
182
  export type {
@@ -17,8 +17,6 @@
17
17
  disabled?: boolean;
18
18
  };
19
19
 
20
- export type SelectDropdownArrowPosition = false | 'before' | 'after';
21
-
22
20
  export interface SelectProps {
23
21
  /** How large should the button be? */
24
22
  size?: ComponentSize;
@@ -105,7 +103,7 @@
105
103
  /** Dropdown Arrow Icon */
106
104
  customDropdownArrowIcon?: (open: boolean) => Snippet;
107
105
  /** Select Dropdown Arrow Position */
108
- dropdownArrowPosition?: SelectDropdownArrowPosition;
106
+ dropdownArrowPosition?: DropdownArrowPosition;
109
107
  /** Popup stick horizontally */
110
108
  popupPositionX?: PositionX;
111
109
  /** Popup stick vertically */
@@ -138,6 +136,7 @@
138
136
  } from '$lib/index.js';
139
137
  import type { TextInputInputEvent } from '../TextInput/TextInput.svelte';
140
138
  import type { ButtonClickEvent } from '../Button/Button.svelte';
139
+ import type { DropdownArrowPosition } from '$lib/types/special.js';
141
140
 
142
141
  let {
143
142
  size = 'normal',
@@ -0,0 +1,195 @@
1
+ <script lang="ts" module>
2
+ import type { ComponentSize } from '$lib/types/size.js';
3
+ import type { DropdownArrowPosition } from '$lib/types/special.js';
4
+ import Icon from '@iconify/svelte';
5
+ import { onMount, type Snippet } from 'svelte';
6
+ import type { EventHandler } from 'svelte/elements';
7
+
8
+ export type AccordianToggleEvent = Event & {
9
+ currentTarget: EventTarget & HTMLDetailsElement;
10
+ };
11
+
12
+ export interface AccordianProps {
13
+ /** Contents goes here */
14
+ children?: Snippet;
15
+ /** Accordian summary */
16
+ summary?: Snippet;
17
+ /** summary full width */
18
+ fullWidthSummary?: boolean;
19
+ /** Accordian ref */
20
+ ref?: HTMLDetailsElement;
21
+ /** Custom css class */
22
+ class?: string;
23
+ /** The toggle event handler */
24
+ ontoggle?: EventHandler<Event, HTMLDetailsElement>;
25
+ /** Open state, for dynmaic Accordians */
26
+ open?: boolean;
27
+ /** default Open, for static Accordians */
28
+ defaultOpen?: boolean;
29
+ /** How large should the button be? */
30
+ size?: ComponentSize;
31
+ /** Select Dropdown Arrow Position */
32
+ dropdownArrowPosition?: DropdownArrowPosition;
33
+ /** Dropdown Arrow Icon */
34
+ customDropdownArrowIcon?: (open: boolean) => Snippet;
35
+ }
36
+ </script>
37
+
38
+ <script lang="ts">
39
+ let {
40
+ class: className = '',
41
+ ref = $bindable<HTMLDetailsElement>(),
42
+ ontoggle,
43
+ open = $bindable<boolean>(),
44
+ defaultOpen,
45
+ summary,
46
+ children,
47
+ size = 'normal',
48
+ fullWidthSummary = false,
49
+ customDropdownArrowIcon: customDropdownArrowIconInternal,
50
+ dropdownArrowPosition = 'before',
51
+ }: AccordianProps = $props();
52
+
53
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
54
+ let customDropdownArrowIconTyped = customDropdownArrowIconInternal as any;
55
+
56
+ let isUserInteraction = $state(false);
57
+
58
+ function ontoggleMod(e: AccordianToggleEvent) {
59
+ if (isUserInteraction) {
60
+ if (ontoggle) {
61
+ ontoggle(e);
62
+ }
63
+ }
64
+
65
+ isUserInteraction = false;
66
+ }
67
+
68
+ function onsummaryclick() {
69
+ isUserInteraction = true;
70
+ }
71
+
72
+ onMount(() => {
73
+ if (open === true) {
74
+ ref.open = true;
75
+ } else if (open === false) {
76
+ ref.open = false;
77
+ } else if (defaultOpen === true) {
78
+ ref.open = true;
79
+ } else if (defaultOpen === false) {
80
+ ref.open = false;
81
+ }
82
+ });
83
+ </script>
84
+
85
+ {#snippet dropdownArrowIcon()}
86
+ {#if customDropdownArrowIconTyped}
87
+ {@render customDropdownArrowIconTyped(open)}
88
+ {:else}
89
+ <div class="IconOpen">
90
+ <Icon icon="material-symbols:arrow-drop-up-rounded" width="32" height="32" />
91
+ </div>
92
+ <div class="IconClose">
93
+ <Icon icon="material-symbols:arrow-drop-down-rounded" width="32" height="32" />
94
+ </div>
95
+ {/if}
96
+ {/snippet}
97
+
98
+ <details
99
+ class:fullWidthSummary
100
+ class={['dodo-ui-Accordian', `size--${size}`, className].join(' ')}
101
+ bind:this={ref}
102
+ {open}
103
+ ontoggle={ontoggleMod}
104
+ >
105
+ {#if summary}
106
+ <summary onclick={onsummaryclick}>
107
+ {#if dropdownArrowPosition === 'before'}
108
+ <div class:open class="DropdownArrow before">
109
+ {@render dropdownArrowIcon()}
110
+ </div>
111
+ {/if}
112
+ {@render summary()}
113
+ {#if dropdownArrowPosition === 'after'}
114
+ <div class:open class="DropdownArrow after">
115
+ {@render dropdownArrowIcon()}
116
+ </div>
117
+ {/if}
118
+ </summary>
119
+ {/if}
120
+
121
+ {#if children}
122
+ <div class="AccordianContent">
123
+ {@render children()}
124
+ </div>
125
+ {/if}
126
+ </details>
127
+
128
+ <style lang="scss">
129
+ .dodo-ui-Accordian {
130
+ color: var(--dodo-color-neutral-900);
131
+ width: 100%;
132
+
133
+ summary {
134
+ display: inline-flex;
135
+ align-items: center;
136
+ cursor: pointer;
137
+ user-select: none;
138
+ font-weight: 500;
139
+ }
140
+
141
+ &.fullWidthSummary {
142
+ summary {
143
+ display: flex;
144
+ width: 100%;
145
+ }
146
+ }
147
+
148
+ &[open] {
149
+ .IconOpen {
150
+ display: flex;
151
+ }
152
+
153
+ .IconClose {
154
+ display: none;
155
+ }
156
+ }
157
+
158
+ &:not([open]) {
159
+ .IconOpen {
160
+ display: none;
161
+ }
162
+
163
+ .IconClose {
164
+ display: flex;
165
+ }
166
+ }
167
+
168
+ &.size {
169
+ &--normal {
170
+ summary {
171
+ font-size: 1rem;
172
+ min-height: var(--dodo-ui-element-height-normal);
173
+ }
174
+ }
175
+
176
+ &--small {
177
+ summary {
178
+ font-size: 0.9rem;
179
+ min-height: var(--dodo-ui-element-height-small);
180
+ }
181
+ }
182
+
183
+ &--large {
184
+ summary {
185
+ font-size: 1.1rem;
186
+ min-height: var(--dodo-ui-element-height-large);
187
+ }
188
+ }
189
+ }
190
+
191
+ .AccordianContent {
192
+ margin-top: var(--dodo-ui-space);
193
+ }
194
+ }
195
+ </style>
@@ -0,0 +1 @@
1
+ export type DropdownArrowPosition = false | 'before' | 'after';