@agnos-ui/svelte-headless 0.4.4 → 0.5.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/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  [![npm](https://img.shields.io/npm/v/@agnos-ui/svelte-headless)](https://www.npmjs.com/package/@agnos-ui/svelte-headless)
4
4
 
5
- Headless widget library for [Svelte](https://svelte.dev/).
5
+ Headless component library for [Svelte](https://svelte.dev/).
6
6
 
7
7
  ## Installation
8
8
 
@@ -12,4 +12,4 @@ npm install @agnos-ui/svelte-headless
12
12
 
13
13
  ## Usage
14
14
 
15
- Please check [our demo site](https://amadeusitgroup.github.io/AgnosUI/latest/) to see all the available widgets and how to use them.
15
+ Please check [our demo site](https://www.agnosui.dev/latest/) to see all the available components and how to use them.
package/Slot.svelte CHANGED
@@ -1,24 +1,19 @@
1
- <script lang="ts">
2
- import type {SlotContent, SlotSvelteComponent} from './types';
3
- import {isSvelteComponent} from './utils/widget';
4
- import {useSvelteSlot} from './types';
5
- type Props = $$Generic<object>; // eslint-disable-line no-undef
6
- // cf https://github.com/ota-meshi/eslint-plugin-svelte/issues/348
7
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
8
- type $$Slots = {
9
- default: {component: SlotSvelteComponent<Props>; props: Props};
10
- slot: {props: Props};
11
- };
12
- export let slotContent: SlotContent<Props> = null;
13
- export let props: Props;
1
+ <script lang="ts" generics="Props extends object">
2
+ import type {SlotContent} from './types';
3
+
4
+ let {
5
+ content,
6
+ props,
7
+ }: {
8
+ content: SlotContent<Props>;
9
+ props: Props;
10
+ } = $props();
14
11
  </script>
15
12
 
16
- {#if slotContent === useSvelteSlot}
17
- <slot name="slot" {props} />
18
- {:else if typeof slotContent === 'string'}
19
- {slotContent}
20
- {:else if slotContent && !isSvelteComponent(slotContent)}
21
- {slotContent(props)}
22
- {:else if slotContent}
23
- <slot component={slotContent} {props} />
13
+ {#if content}
14
+ {#if typeof content === 'string'}
15
+ {content}
16
+ {:else}
17
+ {@render content(props)}
18
+ {/if}
24
19
  {/if}
package/Slot.svelte.d.ts CHANGED
@@ -1,25 +1,21 @@
1
- import {SvelteComponentTyped} from 'svelte';
2
- import type {SlotSvelteComponent, SlotContent} from './types';
1
+ import type { SlotContent } from './types';
3
2
  declare class __sveltets_Render<Props extends object> {
4
- props(): {
5
- slotContent?: SlotContent<Props>;
6
- props: Props;
7
- };
8
- events(): {
9
- [evt: string]: CustomEvent<any>;
10
- };
11
- slots(): {
12
- default: {
13
- component: SlotSvelteComponent<Props>;
14
- props: Props;
15
- };
16
- slot: {
17
- props: Props;
18
- };
19
- };
3
+ props(): {
4
+ content: SlotContent<Props>;
5
+ props: Props;
6
+ };
7
+ events(): {};
8
+ slots(): {};
9
+ bindings(): "";
10
+ exports(): {};
20
11
  }
21
- export type SlotProps<Props extends object> = ReturnType<__sveltets_Render<Props>['props']>;
22
- export type SlotEvents<Props extends object> = ReturnType<__sveltets_Render<Props>['events']>;
23
- export type SlotSlots<Props extends object> = ReturnType<__sveltets_Render<Props>['slots']>;
24
- export default class Slot<Props extends object> extends SvelteComponentTyped<SlotProps<Props>, SlotEvents<Props>, SlotSlots<Props>> {}
25
- export {};
12
+ interface $$IsomorphicComponent {
13
+ new <Props extends object>(options: import('svelte').ComponentConstructorOptions<ReturnType<__sveltets_Render<Props>['props']>>): import('svelte').SvelteComponent<ReturnType<__sveltets_Render<Props>['props']>, ReturnType<__sveltets_Render<Props>['events']>, ReturnType<__sveltets_Render<Props>['slots']>> & {
14
+ $$bindings?: ReturnType<__sveltets_Render<Props>['bindings']>;
15
+ } & ReturnType<__sveltets_Render<Props>['exports']>;
16
+ <Props extends object>(internal: unknown, props: ReturnType<__sveltets_Render<Props>['props']> & {}): ReturnType<__sveltets_Render<Props>['exports']>;
17
+ z_$$bindings?: ReturnType<__sveltets_Render<any>['bindings']>;
18
+ }
19
+ declare const Slot: $$IsomorphicComponent;
20
+ type Slot<Props extends object> = InstanceType<typeof Slot<Props>>;
21
+ export default Slot;
package/config.d.ts CHANGED
@@ -1,16 +1,16 @@
1
1
  import type { Partial2Levels, WidgetsConfigStore } from '@agnos-ui/core/config';
2
2
  import type { ReadableSignal } from '@amadeus-it-group/tansu';
3
- import type { SlotsPresent, Widget, WidgetProps, WidgetFactory } from './types';
3
+ import type { Widget, WidgetProps, WidgetFactory } from './types';
4
4
  export * from '@agnos-ui/core/config';
5
5
  type WidgetFactoryInput<Config extends {
6
6
  [widgetName: string]: object;
7
7
  }, W extends Widget> = {
8
8
  factory: WidgetFactory<W>;
9
9
  widgetName?: null | keyof Config;
10
- $$slots?: SlotsPresent<WidgetProps<W>>;
11
10
  defaultConfig?: Partial<WidgetProps<W>> | ReadableSignal<Partial<WidgetProps<W>> | undefined>;
12
- events?: Pick<WidgetProps<W>, keyof WidgetProps<W> & `on${string}Change`>;
13
- $$props: Partial<WidgetProps<W>>;
11
+ events?: Partial<Pick<WidgetProps<W>, keyof WidgetProps<W> & `on${string}Change`>>;
12
+ props?: Partial<WidgetProps<W>>;
13
+ enablePatchChanged?: true;
14
14
  };
15
15
  type AdaptParentConfig<Config> = (config: Partial2Levels<Config>) => Partial2Levels<Config>;
16
16
  type CreateWidgetsDefaultConfig<Config extends {
@@ -21,6 +21,7 @@ type CreateWidgetsDefaultConfig<Config extends {
21
21
  *
22
22
  * It can be used when extending the core and creating new widgets.
23
23
  *
24
+ * @template Config - The shape of the widgets configuration object.
24
25
  * @param widgetsDefaultConfigKey - the widgets config key
25
26
  * @returns the utilities to create / manage widgets and contexts
26
27
  */
@@ -33,10 +34,6 @@ export declare const widgetsConfigFactory: <Config extends {
33
34
  widgetsDefaultConfigKey: symbol;
34
35
  createWidgetsDefaultConfig: CreateWidgetsDefaultConfig<Config>;
35
36
  getContextWidgetConfig: <N extends keyof Config>(widgetName: N) => ReadableSignal<Partial<Config[N]> | undefined>;
36
- callWidgetFactory: <W extends Widget>({ factory, widgetName, $$slots, defaultConfig, events, $$props, }: WidgetFactoryInput<Config, W>) => W & {
37
- patchChangedProps: W["patch"];
38
- };
39
- };
40
- export declare const widgetsDefaultConfigKey: symbol, createWidgetsDefaultConfig: CreateWidgetsDefaultConfig<WidgetsConfig>, getContextWidgetConfig: <N extends string | number | symbol>(widgetName: N) => ReadableSignal<any>, callWidgetFactory: <W extends Widget>({ factory, widgetName, $$slots, defaultConfig, events, $$props, }: WidgetFactoryInput<WidgetsConfig, W>) => W & {
41
- patchChangedProps: W["patch"];
37
+ callWidgetFactory: <W extends Widget>(input: WidgetFactoryInput<Config, W>) => WidgetSlotContext<W_1>;
42
38
  };
39
+ export declare const widgetsDefaultConfigKey: symbol, createWidgetsDefaultConfig: CreateWidgetsDefaultConfig<WidgetsConfig>, getContextWidgetConfig: <N extends string | number | symbol>(widgetName: N) => ReadableSignal<any>, callWidgetFactory: <W extends Widget>(input: WidgetFactoryInput<WidgetsConfig, W>) => WidgetSlotContext<W_1>;
package/config.js CHANGED
@@ -1,13 +1,14 @@
1
1
  import { createWidgetsConfig } from '@agnos-ui/core/config';
2
2
  import { computed } from '@amadeus-it-group/tansu';
3
3
  import { getContext, setContext } from 'svelte';
4
- import { callWidgetFactoryWithConfig } from './utils/widget';
4
+ import { callWidgetFactoryWithConfig } from './utils/widget.svelte';
5
5
  export * from '@agnos-ui/core/config';
6
6
  /**
7
7
  * A factory to create the utilities to allow widgets to be context-aware.
8
8
  *
9
9
  * It can be used when extending the core and creating new widgets.
10
10
  *
11
+ * @template Config - The shape of the widgets configuration object.
11
12
  * @param widgetsDefaultConfigKey - the widgets config key
12
13
  * @returns the utilities to create / manage widgets and contexts
13
14
  */
@@ -60,13 +61,15 @@ export const widgetsConfigFactory = (widgetsDefaultConfigKey = Symbol('widgetsCo
60
61
  const widgetsConfig = getContext(widgetsDefaultConfigKey);
61
62
  return computed(() => widgetsConfig?.()[widgetName]);
62
63
  };
63
- const callWidgetFactory = ({ factory, widgetName = null, $$slots, defaultConfig = {}, events, $$props, }) => callWidgetFactoryWithConfig({
64
- factory,
65
- $$slots,
66
- defaultConfig,
67
- widgetConfig: widgetName ? getContextWidgetConfig(widgetName) : null,
68
- events,
69
- $$props,
64
+ const callWidgetFactory = (input) => callWidgetFactoryWithConfig({
65
+ factory: input.factory,
66
+ defaultConfig: input.defaultConfig,
67
+ widgetConfig: input.widgetName ? getContextWidgetConfig(input.widgetName) : null,
68
+ events: input.events,
69
+ get props() {
70
+ return input.props;
71
+ },
72
+ enablePatchChanged: input.enablePatchChanged,
70
73
  });
71
74
  return {
72
75
  /**
@@ -17,9 +17,8 @@ export * from './utils/stores';
17
17
  export * from './utils/directive';
18
18
  export * from './types';
19
19
  export * from './config';
20
- export * from './utils/widget';
20
+ export * from './utils/widget.svelte';
21
21
  export * from './slot';
22
- export * from './Slot.svelte.d';
23
22
  export * from './components/toast/index';
24
23
  export * from './components/slider/index';
25
24
  export * from './components/select/index';
@@ -17,9 +17,8 @@ export * from './utils/stores';
17
17
  export * from './utils/directive';
18
18
  export * from './types';
19
19
  export * from './config';
20
- export * from './utils/widget';
20
+ export * from './utils/widget.svelte';
21
21
  export * from './slot';
22
- export * from './Slot.svelte.d';
23
22
  export * from './components/toast/index';
24
23
  export * from './components/slider/index';
25
24
  export * from './components/select/index';
@@ -0,0 +1 @@
1
+ export * from './../../utils/widget.svelte';
@@ -0,0 +1 @@
1
+ export * from './../../utils/widget.svelte';
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@agnos-ui/svelte-headless",
3
- "description": "Headless widget library for Svelte.",
4
- "version": "0.4.4",
3
+ "description": "Headless component library for Svelte.",
4
+ "version": "0.5.0",
5
5
  "type": "module",
6
6
  "main": "./index.js",
7
7
  "module": "./index.js",
@@ -49,14 +49,14 @@
49
49
  }
50
50
  },
51
51
  "dependencies": {
52
- "@agnos-ui/core": "0.4.4"
52
+ "@agnos-ui/core": "0.5.0"
53
53
  },
54
54
  "peerDependencies": {
55
55
  "@amadeus-it-group/tansu": "^1.0.0",
56
- "svelte": "^4.2.18"
56
+ "svelte": "^5.1.4"
57
57
  },
58
58
  "sideEffects": false,
59
- "homepage": "https://amadeusitgroup.github.io/AgnosUI/latest/",
59
+ "homepage": "https://www.agnosui.dev/latest/",
60
60
  "bugs": "https://github.com/AmadeusITGroup/AgnosUI/issues",
61
61
  "license": "MIT",
62
62
  "repository": {
@@ -70,6 +70,7 @@
70
70
  "accordion",
71
71
  "AgnosUI",
72
72
  "alert",
73
+ "collapse",
73
74
  "components",
74
75
  "modal",
75
76
  "pagination",
package/types.d.ts CHANGED
@@ -1,13 +1,9 @@
1
1
  export * from '@agnos-ui/core/types';
2
- import type { SlotContent as CoreSlotContent, Extends, WidgetProps, WidgetSlotContext } from '@agnos-ui/core/types';
3
- import type { ComponentType, SvelteComponent } from 'svelte';
4
- export declare const useSvelteSlot: unique symbol;
5
- export type IsSlotContent<T> = Extends<T, SlotContent<any>> | Extends<SlotContent<any>, T> extends 1 ? T : 0;
6
- export type WidgetPropsSlots<Props extends object> = {
7
- [K in keyof Props as IsSlotContent<Props[K]> extends SlotContent<any> ? K extends 'children' ? 'default' : K extends `slot${infer U}` ? Uncapitalize<U> : K : never]: Props[K] extends SlotContent<infer U> ? U : never;
8
- };
9
- export type SlotsPresent<Props extends object> = {
10
- [K in keyof Props as IsSlotContent<Props[K]> extends SlotContent<any> ? K extends 'children' ? 'default' : K extends `slot${infer U}` ? Uncapitalize<U> : K : never]?: boolean;
11
- };
12
- export type SlotSvelteComponent<Props extends object = object> = ComponentType<SvelteComponent<Props, any, Props extends WidgetSlotContext<infer U> ? WidgetPropsSlots<WidgetProps<U>> : any>>;
13
- export type SlotContent<Props extends object = object> = CoreSlotContent<Props> | SlotSvelteComponent<Props> | typeof useSvelteSlot;
2
+ import type { Snippet } from 'svelte';
3
+ /**
4
+ * Represents the content of a slot, which can either be a `string` or a `Snippet`.
5
+ *
6
+ * @template Props - The type of the properties that the Snippet can accept.
7
+ * @see {@link https://svelte.dev/docs/svelte/snippet}
8
+ */
9
+ export type SlotContent<Props extends object = object> = string | Snippet<[Props]>;
package/types.js CHANGED
@@ -1,2 +1 @@
1
1
  export * from '@agnos-ui/core/types';
2
- export const useSvelteSlot = Symbol('useSvelteSlot');
@@ -0,0 +1,22 @@
1
+ import type { ReadableSignal } from '@amadeus-it-group/tansu';
2
+ import type { Widget, WidgetFactory, WidgetProps, WidgetSlotContext } from '../types';
3
+ /**
4
+ * Call a widget factory using provided configs.
5
+ *
6
+ * @param parameter - the parameter
7
+ * @param parameter.factory - the widget factory to call
8
+ * @param parameter.defaultConfig - the default config of the widget
9
+ * @param parameter.widgetConfig - the config of the widget, overriding the defaultConfig
10
+ * @param parameter.events - the events of the widget
11
+ * @param parameter.props - the props of the widget
12
+ * @param parameter.enablePatchChanged - enable patching changed props
13
+ * @returns the widget
14
+ */
15
+ export declare const callWidgetFactoryWithConfig: <W extends Widget>(parameter: {
16
+ factory: WidgetFactory<W>;
17
+ defaultConfig?: Partial<WidgetProps<W>> | ReadableSignal<Partial<WidgetProps<W>> | undefined>;
18
+ widgetConfig?: null | undefined | ReadableSignal<Partial<WidgetProps<W>> | undefined>;
19
+ events?: Partial<Pick<WidgetProps<W>, keyof WidgetProps<W> & `on${string}Change`>>;
20
+ props?: Partial<WidgetProps<W>>;
21
+ enablePatchChanged?: true;
22
+ }) => WidgetSlotContext<W>;
@@ -1,6 +1,6 @@
1
1
  import { findChangedProperties, toReadableStore } from '@agnos-ui/core/utils/stores';
2
2
  import { asWritable, computed, writable } from '@amadeus-it-group/tansu';
3
- import { useSvelteSlot } from '../types';
3
+ import { fromStore } from 'svelte/store';
4
4
  function createPatchChangedProps(previousProps, patchFn) {
5
5
  return (props) => {
6
6
  const changedProps = findChangedProperties(previousProps, props);
@@ -41,46 +41,44 @@ const eventStore = (event, prop) => {
41
41
  *
42
42
  * @param parameter - the parameter
43
43
  * @param parameter.factory - the widget factory to call
44
- * @param parameter.$$slots - the slots of the widget
45
44
  * @param parameter.defaultConfig - the default config of the widget
46
45
  * @param parameter.widgetConfig - the config of the widget, overriding the defaultConfig
47
46
  * @param parameter.events - the events of the widget
48
- * @param parameter.$$props - the props of the widget
47
+ * @param parameter.props - the props of the widget
48
+ * @param parameter.enablePatchChanged - enable patching changed props
49
49
  * @returns the widget
50
50
  */
51
- export const callWidgetFactoryWithConfig = ({ factory, $$slots, defaultConfig, widgetConfig, events, $$props, }) => {
51
+ export const callWidgetFactoryWithConfig = (parameter) => {
52
+ const { factory, defaultConfig, widgetConfig, events, enablePatchChanged } = parameter;
53
+ const props = parameter.props ?? {};
52
54
  const defaultConfig$ = toReadableStore(defaultConfig);
53
- const processedSlots = {};
54
- if ($$slots) {
55
- for (const [name, present] of Object.entries($$slots)) {
56
- if (present) {
57
- processedSlots[name === 'default' ? 'children' : name] = useSvelteSlot;
58
- }
59
- }
60
- }
61
- const props = { ...$$props };
55
+ const propsWithEvents = { ...props };
62
56
  if (events) {
63
57
  for (const event of Object.keys(events)) {
64
- props[event] = eventStore(events[event], $$props[event]);
58
+ propsWithEvents[event] = eventStore(events[event], props[event]);
65
59
  }
66
60
  }
67
61
  const widget = factory({
68
- config: computed(() => ({ ...defaultConfig$(), ...widgetConfig?.(), ...processedSlots })),
69
- props,
62
+ config: computed(() => ({ ...defaultConfig$(), ...widgetConfig?.() })),
63
+ props: propsWithEvents,
70
64
  });
71
- return { ...widget, patchChangedProps: createPatchChangedProps($$props, widget.patch) };
72
- };
73
- /**
74
- * A type guard checking if a provided slot content is a Svelte component.
75
- *
76
- * @param content - the slot content
77
- * @returns true if the slot content is a svelte component
78
- */
79
- export const isSvelteComponent = (content) => {
80
- // in prod mode, a svelte component has $set on its prototype
81
- // in dev mode with hmr (hot module reload), a svelte component has nothing on its prototype, but its name starts with Proxy<
82
- return ((typeof content === 'function' && !!content.prototype && (content.prototype.$set || /^Proxy</.test(content.name))) ||
83
- // when using Server Side Rendering, a svelte component is an object with a render function:
84
- // (cf https://svelte.dev/docs/server-side-component-api)
85
- typeof content?.render === 'function');
65
+ const runes = Object.fromEntries(Object.entries(widget.stores).map(([key, val]) => [key.slice(0, -1), fromStore(val)]));
66
+ if (enablePatchChanged) {
67
+ const patch = createPatchChangedProps(props, widget.patch);
68
+ $effect(() => {
69
+ patch({ ...parameter.props });
70
+ });
71
+ }
72
+ return {
73
+ api: widget.api,
74
+ directives: widget.directives,
75
+ state: new Proxy(runes, {
76
+ get(target, name, receiver) {
77
+ if (Reflect.has(target, name)) {
78
+ return Reflect.get(target, name, receiver).current;
79
+ }
80
+ return undefined;
81
+ },
82
+ }),
83
+ };
86
84
  };
@@ -1 +0,0 @@
1
- export * from './../Slot.svelte.d';
@@ -1 +0,0 @@
1
- export * from './../../utils/widget';
@@ -1 +0,0 @@
1
- export * from './../../utils/widget';
package/utils/widget.d.ts DELETED
@@ -1,31 +0,0 @@
1
- import type { ReadableSignal } from '@amadeus-it-group/tansu';
2
- import type { SlotContent, SlotSvelteComponent, SlotsPresent, Widget, WidgetFactory, WidgetProps } from '../types';
3
- /**
4
- * Call a widget factory using provided configs.
5
- *
6
- * @param parameter - the parameter
7
- * @param parameter.factory - the widget factory to call
8
- * @param parameter.$$slots - the slots of the widget
9
- * @param parameter.defaultConfig - the default config of the widget
10
- * @param parameter.widgetConfig - the config of the widget, overriding the defaultConfig
11
- * @param parameter.events - the events of the widget
12
- * @param parameter.$$props - the props of the widget
13
- * @returns the widget
14
- */
15
- export declare const callWidgetFactoryWithConfig: <W extends Widget>({ factory, $$slots, defaultConfig, widgetConfig, events, $$props, }: {
16
- factory: WidgetFactory<W>;
17
- $$slots?: SlotsPresent<WidgetProps<W>>;
18
- defaultConfig?: Partial<WidgetProps<W>> | ReadableSignal<Partial<WidgetProps<W>> | undefined>;
19
- widgetConfig?: null | undefined | ReadableSignal<Partial<WidgetProps<W>> | undefined>;
20
- events?: Pick<WidgetProps<W>, keyof WidgetProps<W> & `on${string}Change`>;
21
- $$props: Partial<WidgetProps<W>>;
22
- }) => W & {
23
- patchChangedProps: W["patch"];
24
- };
25
- /**
26
- * A type guard checking if a provided slot content is a Svelte component.
27
- *
28
- * @param content - the slot content
29
- * @returns true if the slot content is a svelte component
30
- */
31
- export declare const isSvelteComponent: <Props extends object>(content: SlotContent<Props>) => content is SlotSvelteComponent<Props>;