fuma 0.1.10 → 0.1.13

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/Meta.svelte CHANGED
@@ -1,9 +1,12 @@
1
1
  <script>import {} from "svelte";
2
- import { Card, Table } from "./index.js";
2
+ import { Card, Table, Icon } from "./index.js";
3
+ import { mdiEyeOffOutline, mdiEyeOutline } from "@mdi/js";
4
+ import { slide } from "svelte/transition";
3
5
  export let name = "";
4
6
  export let description = "";
5
7
  export let component;
6
8
  let props = [];
9
+ let isPropsVisible = false;
7
10
  $:
8
11
  initMeta(component);
9
12
  function initMeta(c) {
@@ -23,33 +26,45 @@ function updateComponentMeta(c) {
23
26
  </script>
24
27
 
25
28
  <Card class="mx-auto mt-6 max-w-4xl">
26
- <svelte:fragment slot="title">{name}</svelte:fragment>
29
+ <div slot="title" class="flex items-center gap-4">
30
+ <span class="grow">{name}</span>
31
+ <button class="btn btn-square btn-sm" on:click={() => (isPropsVisible = !isPropsVisible)}>
32
+ <Icon
33
+ size={20}
34
+ title="Affichage des props"
35
+ path={isPropsVisible ? mdiEyeOutline : mdiEyeOffOutline}
36
+ />
37
+ </button>
38
+ </div>
39
+
27
40
  <svelte:fragment slot="subtitle">{description}</svelte:fragment>
28
41
 
29
42
  <slot />
30
43
 
31
- <div class="my-10" />
32
-
33
- <Table
34
- items={props}
35
- fields={[
36
- {
37
- key: 'name',
38
- label: 'Prop',
39
- getCell: (p) => p.id,
40
- locked: true
41
- },
42
- {
43
- key: 'type',
44
- label: 'Type',
45
- getCell: (p) => typeof p.value
46
- },
47
- {
48
- key: 'value',
49
- label: 'Value',
50
- getCell: (p) => p.value,
51
- visible: true
52
- }
53
- ]}
54
- ></Table>
44
+ {#if isPropsVisible}
45
+ <div transition:slide class="pt-6">
46
+ <Table
47
+ items={props}
48
+ fields={[
49
+ {
50
+ key: 'name',
51
+ label: 'Prop',
52
+ getCell: (p) => p.id,
53
+ locked: true
54
+ },
55
+ {
56
+ key: 'type',
57
+ label: 'Type',
58
+ getCell: (p) => typeof p.value
59
+ },
60
+ {
61
+ key: 'value',
62
+ label: 'Value',
63
+ getCell: (p) => p.value,
64
+ visible: true
65
+ }
66
+ ]}
67
+ />
68
+ </div>
69
+ {/if}
55
70
  </Card>
@@ -2,7 +2,7 @@
2
2
  import { onMount } from "svelte";
3
3
  export let path;
4
4
  export let title = "";
5
- export let size = 24;
5
+ export let size = 22;
6
6
  let klass = "";
7
7
  export { klass as class };
8
8
  export let style = "";
@@ -1,29 +1,29 @@
1
1
  <script>import { createEventDispatcher } from "svelte";
2
2
  import { FormControl, bindCheckedWithParams } from "./index.js";
3
3
  $:
4
- ({ input, value: _value, bindWithParams, label, ...props } = $$props);
4
+ ({ input, value: _value, bindWithParams, label, ...props } = $$restProps);
5
5
  export let value = _value;
6
6
  const dispatch = createEventDispatcher();
7
7
  </script>
8
8
 
9
9
  <FormControl {...props} let:key>
10
- <div class="flex items-center gap-2">
11
- <input type="hidden" name={key} value={value ? 'true' : ''} />
12
- <input
13
- bind:checked={value}
14
- use:bindCheckedWithParams={{ bindEnable: bindWithParams }}
15
- on:input={({ currentTarget: { checked } }) => dispatch('change', checked)}
16
- on:focus
17
- on:blur
18
- type="checkbox"
19
- id={key}
20
- class="checkbox"
21
- {...input}
22
- />
23
- <label for={key} class="label cursor-pointer">
24
- <span class="label-text">
25
- <slot>{label}</slot>
26
- </span>
27
- </label>
28
- </div>
10
+ <label for={key} class="label cursor-pointer">
11
+ <span class="label-text">
12
+ <slot>{label}</slot>
13
+ </span>
14
+ </label>
15
+
16
+ <input
17
+ bind:checked={value}
18
+ use:bindCheckedWithParams={{ bindEnable: bindWithParams }}
19
+ on:input={({ currentTarget: { checked } }) => dispatch('change', checked)}
20
+ on:focus
21
+ on:blur
22
+ type="checkbox"
23
+ id={key}
24
+ class="checkbox ml-1"
25
+ {...input}
26
+ />
27
+
28
+ <input type="hidden" name={key} value={value ? 'true' : ''} />
29
29
  </FormControl>
@@ -0,0 +1,84 @@
1
+ <script>import { createEventDispatcher, tick } from "svelte";
2
+ import { parseOptions } from "../../utils/options.js";
3
+ import { FormControl, DropDown, Icon, SelectorList } from "../index.js";
4
+ $:
5
+ ({ input, value: _value, options, tippyProps, ...props } = $$props);
6
+ export let value = _value;
7
+ export let inputElement = void 0;
8
+ let focusIndex = 0;
9
+ let searchValue = "";
10
+ const dispatch = createEventDispatcher();
11
+ let filteredOptions = [];
12
+ $:
13
+ _options = parseOptions(options);
14
+ $:
15
+ selectedOption = _options.find((opt) => opt.value === value);
16
+ function filterOptions(value2) {
17
+ const reg = new RegExp(value2, "i");
18
+ filteredOptions = _options.filter((opt) => opt.label.match(reg) || opt.value.match(reg)).map((opt) => ({ id: opt.value, ...opt }));
19
+ }
20
+ export async function clear() {
21
+ searchValue = "";
22
+ value = "";
23
+ filterOptions("");
24
+ await tick();
25
+ inputElement?.focus();
26
+ }
27
+ async function select(index = focusIndex) {
28
+ value = _options[index].value;
29
+ dispatch("input", value);
30
+ }
31
+ </script>
32
+
33
+ <DropDown {tippyProps} isWidthOfActivator>
34
+ <div class="contents" slot="activator">
35
+ <FormControl {...props} let:key>
36
+ <div class="flex grow gap-2" class:hidden={selectedOption}>
37
+ <div class="relative flex grow items-center gap-2">
38
+ <input
39
+ type="text"
40
+ id={key}
41
+ bind:this={inputElement}
42
+ bind:value={searchValue}
43
+ on:focus={() => filterOptions('')}
44
+ on:blur={() => (searchValue = '')}
45
+ on:input={(e) => filterOptions(e.currentTarget.value)}
46
+ autocomplete="off"
47
+ class="input input-bordered grow"
48
+ {...input}
49
+ />
50
+ </div>
51
+ <slot name="append" />
52
+ </div>
53
+
54
+ {#if selectedOption}
55
+ <button
56
+ type="button"
57
+ class="flex h-12 items-center gap-2 rounded-lg border pl-4 pr-2"
58
+ on:click={clear}
59
+ on:focus={clear}
60
+ >
61
+ {#if selectedOption.icon}
62
+ <Icon path={selectedOption.icon} size={21} class="opacity-70" />
63
+ {/if}
64
+ <span>{selectedOption.label}</span>
65
+ </button>
66
+ <input type="hidden" name={key} value={selectedOption.value} />
67
+ {/if}
68
+ </FormControl>
69
+ </div>
70
+
71
+ <SelectorList
72
+ items={filteredOptions}
73
+ trigger={inputElement}
74
+ {focusIndex}
75
+ let:item
76
+ class="w-full"
77
+ on:select={({ detail }) => select(detail)}
78
+ >
79
+ {#if item.icon}
80
+ <Icon path={item.icon} size={21} class="opacity-70" />
81
+ {/if}
82
+ <span class="whitespace-nowrap pr-4">{item.label}</span>
83
+ </SelectorList>
84
+ </DropDown>
@@ -0,0 +1,42 @@
1
+ import { SvelteComponent } from "svelte";
2
+ import type { TippyProps } from '../../index.js';
3
+ import { type Options } from '../../utils/options.js';
4
+ declare const __propDef: {
5
+ props: {
6
+ clear?: (() => Promise<void>) | undefined;
7
+ } & {
8
+ class?: string | undefined;
9
+ classLabel?: string | undefined;
10
+ key?: string | undefined;
11
+ label?: string | undefined;
12
+ error?: string | undefined;
13
+ hint?: string | undefined;
14
+ prefix?: string | number | undefined;
15
+ prefixFor?: string | number | undefined;
16
+ enhanceDisabled?: boolean | undefined;
17
+ } & {
18
+ input?: import("svelte/elements").HTMLInputAttributes | undefined;
19
+ inputElement?: HTMLInputElement | undefined;
20
+ wrapperClass?: string | undefined;
21
+ value?: string | undefined;
22
+ bindWithParams?: boolean | undefined;
23
+ } & {
24
+ options: Options;
25
+ tippyProps?: TippyProps | undefined;
26
+ };
27
+ events: {
28
+ input: CustomEvent<string>;
29
+ } & {
30
+ [evt: string]: CustomEvent<any>;
31
+ };
32
+ slots: {
33
+ append: {};
34
+ };
35
+ };
36
+ export type InputComboProps = typeof __propDef.props;
37
+ export type InputComboEvents = typeof __propDef.events;
38
+ export type InputComboSlots = typeof __propDef.slots;
39
+ export default class InputCombo extends SvelteComponent<InputComboProps, InputComboEvents, InputComboSlots> {
40
+ get clear(): () => Promise<void>;
41
+ }
42
+ export {};
@@ -4,12 +4,12 @@ import { toast } from "svelte-sonner";
4
4
  import { mdiClose } from "@mdi/js";
5
5
  import { FormControl, DropDown, Icon, SelectorList, Slot } from "../index.js";
6
6
  import RelationAfter from "./RelationAfter.svelte";
7
- export let key = "";
7
+ export let key = Math.random().toString();
8
8
  export let label = "";
9
9
  export let search;
10
10
  export let createUrl = "";
11
- export let createTitle = "";
12
- export let item = null;
11
+ export let createTitle = "Nouveau";
12
+ let item = null;
13
13
  export { item as value };
14
14
  export let error = "";
15
15
  export let placeholder = "";
@@ -60,15 +60,15 @@ async function handleBlur() {
60
60
  }
61
61
  </script>
62
62
 
63
- <DropDown {tippyProps} disable={flatMode}>
63
+ <DropDown {tippyProps} disable={flatMode} isWidthOfActivator>
64
64
  <div class="contents" slot="activator">
65
65
  <FormControl {key} {label} {error} class={klass} let:key>
66
66
  <div class="flex grow gap-2" class:hidden={item}>
67
- <div class="relative flex grow items-center gap-2">
67
+ <div class="input input-bordered flex grow items-center pr-2">
68
68
  <input
69
69
  type="text"
70
- id={key}
71
70
  name={key}
71
+ id={key}
72
72
  bind:this={inputElement}
73
73
  bind:value={searchValue}
74
74
  on:input={(e) => searchItemsDebounce(e.currentTarget.value)}
@@ -76,7 +76,7 @@ async function handleBlur() {
76
76
  on:blur={handleBlur}
77
77
  autocomplete="off"
78
78
  {placeholder}
79
- class="input input-bordered grow"
79
+ class="grow"
80
80
  />
81
81
 
82
82
  <RelationAfter {isLoading} {createUrl} {createTitle} />
@@ -19,7 +19,7 @@ let klass = "";
19
19
  export { klass as class };
20
20
  export let classList = "";
21
21
  let proposedItems = [];
22
- export let items = null;
22
+ let items = null;
23
23
  export { items as value };
24
24
  let isLoading = false;
25
25
  let isError = false;
@@ -73,7 +73,7 @@ async function handleBlur() {
73
73
  }
74
74
  </script>
75
75
 
76
- <DropDown bind:this={dropdown} disable={flatMode}>
76
+ <DropDown bind:this={dropdown} disable={flatMode} isWidthOfActivator>
77
77
  <div slot="activator">
78
78
  <FormControl {key} {label} {error} class={klass}>
79
79
  <div class="flex flex-col gap-2">
@@ -103,7 +103,7 @@ async function handleBlur() {
103
103
  </div>
104
104
  {/if}
105
105
  <div class="flex grow gap-2">
106
- <div class="relative flex grow items-center gap-2">
106
+ <div class="input input-bordered flex grow items-center pr-2">
107
107
  <input
108
108
  type="text"
109
109
  id={key}
@@ -115,7 +115,7 @@ async function handleBlur() {
115
115
  on:blur={handleBlur}
116
116
  autocomplete="off"
117
117
  {placeholder}
118
- class="input input-bordered grow"
118
+ class="grow"
119
119
  />
120
120
 
121
121
  <RelationAfter {isLoading} {createUrl} {createTitle} />
@@ -1,12 +1,10 @@
1
1
  <script>import { createEventDispatcher, onMount } from "svelte";
2
- import { SelectorList, DropDown, Icon } from "../index.js";
2
+ import { SelectorList, DropDown, Icon, FormControl } from "../index.js";
3
3
  import { parseOptions } from "../../utils/options.js";
4
- export let key = "";
5
- export let value = "";
6
- export let options;
7
- export let noBtnClass = false;
8
- let klass = "";
9
- export { klass as class };
4
+ import { mdiUnfoldMoreHorizontal } from "@mdi/js";
5
+ $:
6
+ ({ input, value: _value, options, tippyProps, placeholder, ...props } = $$props);
7
+ export let value = _value;
10
8
  $:
11
9
  _options = parseOptions(options);
12
10
  $:
@@ -22,26 +20,33 @@ onMount(() => {
22
20
  function onSelect(index) {
23
21
  focusIndex = index;
24
22
  value = _options[index].value;
25
- dispatch("select", value);
23
+ dispatch("input", value);
26
24
  dropDown.hide();
27
25
  }
28
26
  </script>
29
27
 
30
- <input type="hidden" name={key} {value} />
31
-
32
- <DropDown bind:this={dropDown}>
33
- <button bind:this={button} slot="activator" type="button" class:btn={!noBtnClass} class={klass}>
34
- <slot name="btn">
35
- {#if selectedOption}
36
- {#if selectedOption.icon}
37
- <Icon path={selectedOption.icon} size={21} class="opacity-70" />
28
+ <DropDown bind:this={dropDown} isWidthOfActivator>
29
+ <div class="contents" slot="activator">
30
+ <FormControl {...props} let:key>
31
+ <button
32
+ bind:this={button}
33
+ id={key}
34
+ type="button"
35
+ class="flex h-12 items-center gap-2 rounded-lg border pl-4 pr-2"
36
+ >
37
+ {#if selectedOption}
38
+ {#if selectedOption.icon}
39
+ <Icon path={selectedOption.icon} size={21} class="opacity-70" />
40
+ {/if}
41
+ <span>{selectedOption.label}</span>
42
+ {:else if placeholder}
43
+ <span class="opacity-60">{placeholder}</span>
38
44
  {/if}
39
- <span>{selectedOption.label}</span>
40
- {:else}
41
- <slot name="placeholder">Sélection</slot>
42
- {/if}
43
- </slot>
44
- </button>
45
+ <Icon class="ml-auto" path={mdiUnfoldMoreHorizontal} size={18} />
46
+ </button>
47
+ <input type="hidden" name={key} {value} />
48
+ </FormControl>
49
+ </div>
45
50
 
46
51
  <SelectorList
47
52
  trigger={button}
@@ -52,8 +57,8 @@ function onSelect(index) {
52
57
  class="w-full"
53
58
  >
54
59
  {#if item.icon}
55
- <Icon path={item.icon} size={21} class="opacity-70" />
60
+ <Icon path={item.icon} size={18} class="opacity-70" />
56
61
  {/if}
57
- <span class="whitespace-nowrap">{item.label}</span>
62
+ <span class="whitespace-nowrap pr-4">{item.label}</span>
58
63
  </SelectorList>
59
64
  </DropDown>
@@ -1,22 +1,19 @@
1
1
  import { SvelteComponent } from "svelte";
2
+ import { type InputProps } from '../index.js';
2
3
  import { type Options } from '../../utils/options.js';
4
+ import type { TippyProps } from '../../index.js';
3
5
  declare const __propDef: {
4
- props: {
5
- key?: string | undefined;
6
- value?: string | undefined;
6
+ props: Omit<InputProps, "inputElement"> & {
7
7
  options: Options;
8
- noBtnClass?: boolean | undefined;
9
- class?: string | undefined;
8
+ tippyProps?: TippyProps | undefined;
9
+ placeholder?: string | undefined;
10
10
  };
11
11
  events: {
12
- select: CustomEvent<string>;
12
+ input: CustomEvent<string>;
13
13
  } & {
14
14
  [evt: string]: CustomEvent<any>;
15
15
  };
16
- slots: {
17
- btn: {};
18
- placeholder: {};
19
- };
16
+ slots: {};
20
17
  };
21
18
  export type InputSelectProps = typeof __propDef.props;
22
19
  export type InputSelectEvents = typeof __propDef.events;
@@ -1,16 +1,15 @@
1
1
  <script>import { fade } from "svelte/transition";
2
2
  import { createEventDispatcher } from "svelte";
3
- import { mdiClose, mdiLoading, mdiPlus } from "@mdi/js";
3
+ import { mdiLoading, mdiPlus } from "@mdi/js";
4
4
  import Icon from "../Icon.svelte";
5
5
  export let isLoading;
6
- export let isUnselectable = false;
7
6
  export let createUrl = "";
8
7
  export let createTitle = "";
9
8
  const dispatch = createEventDispatcher();
10
9
  </script>
11
10
 
12
11
  {#if isLoading}
13
- <div class="absolute right-1" class:right-10={createUrl} transition:fade|local>
12
+ <div class:right-10={createUrl} transition:fade|local>
14
13
  <Icon
15
14
  path={mdiLoading}
16
15
  class="w-9"
@@ -19,24 +18,8 @@ const dispatch = createEventDispatcher();
19
18
  </div>
20
19
  {/if}
21
20
 
22
- {#if isUnselectable}
23
- <div class="ml-[4px] hidden -translate-x-[2px] group-hover:block">
24
- <Icon
25
- path={mdiClose}
26
- on:click={() => dispatch('unselect')}
27
- title="Supprimer la sélection"
28
- class="outline-primary-light outline outline-2 hover:bg-primary"
29
- />
30
- </div>
31
- {/if}
32
-
33
21
  {#if createUrl}
34
- <div class="ml-[4px] -translate-x-[2px]">
35
- <Icon
36
- path={mdiPlus}
37
- on:click={() => dispatch('create')}
38
- title={createTitle}
39
- class="btn btn-square"
40
- />
41
- </div>
22
+ <a href={createUrl} class="btn btn-square btn-sm">
23
+ <Icon path={mdiPlus} on:click={() => dispatch('create')} title={createTitle} />
24
+ </a>
42
25
  {/if}
@@ -2,7 +2,6 @@ import { SvelteComponent } from "svelte";
2
2
  declare const __propDef: {
3
3
  props: {
4
4
  isLoading: boolean;
5
- isUnselectable?: boolean | undefined;
6
5
  createUrl?: string | undefined;
7
6
  createTitle?: string | undefined;
8
7
  };
@@ -22,4 +22,5 @@ export { default as InputOptions } from './InputOptions.svelte';
22
22
  export { default as InputSearch } from './InputSearch.svelte';
23
23
  export { default as InputImage, type Crop } from './InputImage.svelte';
24
24
  export { default as InputImagePreview } from './InputImagePreview.svelte';
25
+ export { default as InputCombo } from './InputCombo.svelte';
25
26
  export { default as SelectorList } from './SelectorList.svelte';
@@ -22,4 +22,5 @@ export { default as InputOptions } from './InputOptions.svelte';
22
22
  export { default as InputSearch } from './InputSearch.svelte';
23
23
  export { default as InputImage } from './InputImage.svelte';
24
24
  export { default as InputImagePreview } from './InputImagePreview.svelte';
25
+ export { default as InputCombo } from './InputCombo.svelte';
25
26
  export { default as SelectorList } from './SelectorList.svelte';
@@ -26,6 +26,7 @@ export let hideOnNav = true;
26
26
  export let tip = void 0;
27
27
  export let disable = false;
28
28
  export let content = void 0;
29
+ export let isWidthOfActivator = false;
29
30
  let activator;
30
31
  beforeNavigate(() => hideOnNav && hide());
31
32
  onMount(() => {
@@ -47,6 +48,7 @@ onMount(() => {
47
48
  interactive: true,
48
49
  interactiveDebounce: 50,
49
50
  appendTo: "parent",
51
+ hideOnClick: false,
50
52
  onShown() {
51
53
  if (autofocus)
52
54
  focusables[0]?.select();
@@ -93,6 +95,7 @@ export function setTippyProps(props) {
93
95
 
94
96
  <div class="hidden">
95
97
  <div
98
+ style={isWidthOfActivator ? `width: ${activator?.offsetWidth}px;` : ''}
96
99
  class="{klass} max-h-80 overflow-auto rounded-lg border bg-base-100 p-1 shadow-lg"
97
100
  bind:this={content}
98
101
  >
@@ -15,6 +15,7 @@ declare const __propDef: {
15
15
  tip?: TippyInstance | undefined;
16
16
  disable?: boolean | undefined;
17
17
  content?: HTMLDivElement | undefined;
18
+ isWidthOfActivator?: boolean | undefined;
18
19
  hide?: (() => void) | undefined;
19
20
  show?: (() => void) | undefined;
20
21
  setTippyProps?: ((props: Partial<TippyProps>) => void) | undefined;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fuma",
3
- "version": "0.1.10",
3
+ "version": "0.1.13",
4
4
  "description": "My fullstack material build with sveltekit, daisyui, zod and more",
5
5
  "author": {
6
6
  "name": "Jonas Voisard",
@@ -48,6 +48,7 @@
48
48
  "prettier": "^3.1.1",
49
49
  "prettier-plugin-svelte": "^3.1.2",
50
50
  "prettier-plugin-tailwindcss": "^0.5.9",
51
+ "prisma": "^5.13.0",
51
52
  "publint": "^0.1.9",
52
53
  "svelte": "^4.2.7",
53
54
  "svelte-check": "^3.6.0",
@@ -60,7 +61,7 @@
60
61
  "dependencies": {
61
62
  "@lucia-auth/adapter-prisma": "^4.0.1",
62
63
  "@mdi/js": "^7.4.47",
63
- "@prisma/client": "5.12.1",
64
+ "@prisma/client": "5.13.0",
64
65
  "@tiptap/core": "^2.3.0",
65
66
  "@tiptap/extension-color": "^2.3.0",
66
67
  "@tiptap/extension-highlight": "^2.3.0",
@@ -81,7 +82,6 @@
81
82
  "lucia": "^3.1.1",
82
83
  "mode-watcher": "^0.3.0",
83
84
  "oslo": "^1.2.0",
84
- "prisma": "^5.12.1",
85
85
  "svelte-easy-crop": "^2.0.3",
86
86
  "svelte-sonner": "^0.3.22",
87
87
  "tippy.js": "^6.3.7",