fuma 0.4.4 → 0.4.6

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.
@@ -0,0 +1,7 @@
1
+ type AutoSubmitOption = {
2
+ debounceMs?: number;
3
+ };
4
+ export declare function autoSubmit(form: HTMLFormElement, options?: AutoSubmitOption): {
5
+ destroy: () => void;
6
+ };
7
+ export {};
@@ -0,0 +1,16 @@
1
+ import debounce from 'debounce';
2
+ export function autoSubmit(form, options) {
3
+ const { debounceMs = 0 } = options || {};
4
+ const btn = document.createElement('button');
5
+ btn.type = 'submit';
6
+ btn.style.display = 'none';
7
+ const onChange = debounce(() => btn.click(), debounceMs);
8
+ form.appendChild(btn);
9
+ form.addEventListener('change', onChange);
10
+ function destroy() {
11
+ btn.remove();
12
+ onChange.flush();
13
+ form.removeEventListener('change', onChange);
14
+ }
15
+ return { destroy };
16
+ }
@@ -2,3 +2,4 @@ export * from './selector.js';
2
2
  export * from './tip.js';
3
3
  export * from './portal.js';
4
4
  export * from './list/index.js';
5
+ export * from './autoSubmit.js';
@@ -2,3 +2,4 @@ export * from './selector.js';
2
2
  export * from './tip.js';
3
3
  export * from './portal.js';
4
4
  export * from './list/index.js';
5
+ export * from './autoSubmit.js';
@@ -7,7 +7,6 @@ import { Icon } from "../icon/index.js";
7
7
  import { subscibeDrawerLayers } from "./layers.js";
8
8
  import { contextContainer } from "../context.js";
9
9
  import { drawerFly } from "./drawerFly.js";
10
- import { writable } from "svelte/store";
11
10
  export let title = "";
12
11
  export let key;
13
12
  let klass = "";
@@ -18,6 +17,7 @@ export let classBody = "";
18
17
  export let duration = 180;
19
18
  export let noOverlay = false;
20
19
  export let transitionX = 0;
20
+ export let zIndex = 50;
21
21
  export function open(value = 1, options = {}) {
22
22
  return goto($urlParam.with({ [key]: value }), {
23
23
  ...options,
@@ -43,7 +43,7 @@ onMount(() => {
43
43
  on:click={() => close()}
44
44
  on:keyup={() => close()}
45
45
  transition:fade={{ duration }}
46
- style="z-index: {10 + $index};"
46
+ style="z-index: {zIndex + $index};"
47
47
  class="fixed inset-0 bg-black/15 backdrop-blur-[1.5px] dark:bg-white/15"
48
48
  />
49
49
  {/if}
@@ -60,7 +60,7 @@ onMount(() => {
60
60
  }
61
61
  }}
62
62
  style="
63
- z-index: {10 + $index};
63
+ z-index: {zIndex + $index};
64
64
  max-width: min(100%, {maxWidth});
65
65
  transform: translateX({-$offset * 4}rem);
66
66
  transition-duration: {duration}ms;
@@ -10,6 +10,7 @@ declare const __propDef: {
10
10
  duration?: number | undefined;
11
11
  noOverlay?: boolean | undefined;
12
12
  transitionX?: number | undefined;
13
+ zIndex?: number | undefined;
13
14
  open?: ((value?: number, options?: {
14
15
  replaceState?: boolean | undefined;
15
16
  noScroll?: boolean | undefined;
@@ -17,6 +17,9 @@ onMount(() => {
17
17
  onDestroy(() => {
18
18
  picker?.destroy();
19
19
  });
20
+ export function clear() {
21
+ picker?.clearSelection();
22
+ }
20
23
  async function initTimePicker() {
21
24
  const _Litepicker = (await import("litepicker")).Litepicker;
22
25
  picker?.destroy();
@@ -1,13 +1,14 @@
1
1
  import { SvelteComponent } from "svelte";
2
- import type { Range } from './types.js';
2
+ import type { Range, RangeAsDate } from './types.js';
3
3
  declare const __propDef: {
4
4
  props: {
5
5
  numberOfMonths?: number | undefined;
6
6
  numberOfColumns?: number | undefined;
7
7
  showWeekNumbers?: boolean | undefined;
8
- range?: Range | undefined;
8
+ range?: RangeAsDate | undefined;
9
9
  minDate?: Date | number | string | undefined;
10
10
  maxDate?: Date | number | string | undefined;
11
+ clear?: (() => void) | undefined;
11
12
  };
12
13
  events: {
13
14
  change: CustomEvent<Range>;
@@ -20,5 +21,6 @@ export type RangePickerProps = typeof __propDef.props;
20
21
  export type RangePickerEvents = typeof __propDef.events;
21
22
  export type RangePickerSlots = typeof __propDef.slots;
22
23
  export default class RangePicker extends SvelteComponent<RangePickerProps, RangePickerEvents, RangePickerSlots> {
24
+ get clear(): () => void;
23
25
  }
24
26
  export {};
@@ -1,8 +1,8 @@
1
- <script>import { mdiCalendarMonthOutline, mdiClose } from "@mdi/js";
2
- import dayjs from "dayjs";
1
+ <script>import { mdiCalendarMonthOutline } from "@mdi/js";
3
2
  import { goto } from "$app/navigation";
3
+ import { slide } from "svelte/transition";
4
4
  import { urlParam } from "../../store/param.js";
5
- import { formatRange } from "./format.js";
5
+ import { formatRangeShort } from "./format.js";
6
6
  import { Icon } from "../icon/index.js";
7
7
  import { DropDown } from "../menu/index.js";
8
8
  import { InputTime } from "../input/index.js";
@@ -11,68 +11,64 @@ import { jsonParse } from "../../utils/jsonParse.js";
11
11
  export let minDate = void 0;
12
12
  export let maxDate = void 0;
13
13
  let dropDown;
14
+ let rangePicker;
14
15
  export let key = "range";
15
- export let range = jsonParse($urlParam.get(key), { start: null, end: null });
16
+ export let range = jsonParse($urlParam.get(key), {
17
+ start: null,
18
+ end: null
19
+ });
16
20
  $:
17
21
  isValidPeriod = !!range.start && !!range.end;
18
22
  function getLabel(_range) {
19
23
  if (!_range || !_range.start || !_range.end)
20
- return "P\xE9riodes";
21
- return formatRange(_range);
24
+ return "";
25
+ return formatRangeShort(_range);
22
26
  }
23
- function handleSubmit() {
24
- dropDown.hide();
25
- if (!isValidPeriod)
26
- return;
27
- goto(
28
- $urlParam.with({
29
- [key]: JSON.stringify({
30
- start: range.start?.toJSON(),
31
- end: range.end?.toJSON()
32
- })
33
- }),
34
- { replaceState: true, noScroll: true }
35
- );
36
- }
37
- function handleReset() {
38
- dropDown.hide();
39
- range = { start: null, end: null };
40
- goto($urlParam.without(key), { replaceState: true, noScroll: true });
27
+ async function writeURL() {
28
+ const url = !range.start && !range.end ? $urlParam.without(key) : $urlParam.with({
29
+ [key]: JSON.stringify({
30
+ start: range.start?.toJSON(),
31
+ end: range.end?.toJSON()
32
+ })
33
+ });
34
+ return goto(url, { replaceState: true, noScroll: true });
41
35
  }
42
36
  </script>
43
37
 
44
- <DropDown bind:this={dropDown} on:mouseLeave={handleSubmit} class="max-h-full">
45
- <div slot="activator" class="join">
46
- <button class="btn join-item btn-sm shrink flex-nowrap">
47
- <Icon path={mdiCalendarMonthOutline} class="opacity-60" size={20} />
48
- {getLabel(range)}
49
- </button>
38
+ <DropDown bind:this={dropDown} tippyProps={{ onHidden: writeURL }} class="max-h-full">
39
+ <button slot="activator" class="btn btn-sm">
40
+ <Icon path={mdiCalendarMonthOutline} class="opacity-60" size={20} />
50
41
  {#if isValidPeriod}
51
- <button class="btn btn-square join-item btn-sm" on:click|preventDefault={handleReset}>
52
- <Icon path={mdiClose} class="fill-base-content" />
53
- </button>
42
+ <span
43
+ transition:slide={{ axis: 'x', duration: 200 }}
44
+ class="whitespace-nowrap text-xs font-medium opacity-80"
45
+ >
46
+ {getLabel(range)}
47
+ </span>
54
48
  {/if}
55
- </div>
49
+ </button>
50
+
51
+ <RangePicker bind:this={rangePicker} numberOfMonths={1} bind:range {minDate} {maxDate} />
56
52
 
57
- <form class="flex flex-col" on:submit|preventDefault={handleSubmit}>
58
- <RangePicker numberOfMonths={1} bind:range {minDate} {maxDate} />
53
+ <div class="flex gap-2 p-2">
54
+ <InputTime label="A partir de" bind:value={range.start} enhanceDisabled class="grow" />
55
+ <InputTime label="Jusqu'à" bind:value={range.end} enhanceDisabled class="grow" />
56
+ </div>
59
57
 
60
- <div class="flex gap-2 p-2">
61
- <InputTime
62
- label="A partir de"
63
- value={dayjs(range.start).toDate()}
64
- on:input={({ detail: newDate }) => (range.start = newDate)}
65
- enhanceDisabled
66
- class="grow"
67
- />
68
- <InputTime
69
- label="Jusqu'à"
70
- value={dayjs(range.end).toDate()}
71
- on:input={({ detail: newDate }) => (range.end = newDate)}
72
- enhanceDisabled
73
- class="grow"
74
- />
75
- </div>
76
- <button class="btn m-2"> Valider </button>
77
- </form>
58
+ <div class="m-2 flex justify-end gap-2">
59
+ {#if range.start || range.end}
60
+ <button
61
+ transition:slide
62
+ class="btn btn-ghost"
63
+ on:click={() => {
64
+ range = { start: null, end: null }
65
+ rangePicker.clear()
66
+ dropDown.hide()
67
+ }}
68
+ >
69
+ Effacer
70
+ </button>
71
+ {/if}
72
+ <button class="btn" on:click={() => dropDown.hide()}> Valider </button>
73
+ </div>
78
74
  </DropDown>
@@ -1,11 +1,11 @@
1
1
  import { SvelteComponent } from "svelte";
2
- import { type Range } from './index.js';
2
+ import { type RangeAsDate } from './index.js';
3
3
  declare const __propDef: {
4
4
  props: {
5
5
  minDate?: Date | number | string | undefined;
6
6
  maxDate?: Date | number | string | undefined;
7
7
  key?: string | undefined;
8
- range?: Range | undefined;
8
+ range?: RangeAsDate | undefined;
9
9
  };
10
10
  events: {
11
11
  [evt: string]: CustomEvent<any>;
@@ -1,4 +1,4 @@
1
1
  import type { Range } from './types.js';
2
2
  export declare const formatRange: (range?: Range, placeholder?: string) => string;
3
- export declare const formatRangeShort: (range: Range, placeholder?: string) => string | undefined;
3
+ export declare const formatRangeShort: (range: Range, placeholder?: string) => string;
4
4
  export declare const formatRangeHour: (range: Range, placeholder?: string) => string;
@@ -10,6 +10,7 @@ const formater = new Intl.DateTimeFormat('fr-ch', {
10
10
  });
11
11
  const formaterShort = new Intl.DateTimeFormat('fr-ch', {
12
12
  weekday: 'short',
13
+ month: 'long',
13
14
  hour: 'numeric',
14
15
  minute: 'numeric',
15
16
  timeZone: 'Europe/Zurich'
@@ -35,7 +36,7 @@ export const formatRangeShort = (range, placeholder = '') => {
35
36
  return placeholder;
36
37
  const start = dayjs(range.start).toDate();
37
38
  const end = dayjs(range.end).toDate();
38
- formaterShort.formatRange(start, end);
39
+ return formaterShort.formatRange(start, end);
39
40
  };
40
41
  export const formatRangeHour = (range, placeholder = '') => {
41
42
  if (!isRequiredRange(range))
@@ -4,6 +4,10 @@ export type Range = {
4
4
  start: RangeDate;
5
5
  end: RangeDate;
6
6
  };
7
+ export type RangeAsDate = {
8
+ start: Date | null | undefined;
9
+ end: Date | null | undefined;
10
+ };
7
11
  export type RangeRequired = {
8
12
  start: Date | Dayjs;
9
13
  end: Date | Dayjs;
@@ -10,6 +10,7 @@ import { jsonParse } from "../../../utils/jsonParse.js";
10
10
  import { Icon } from "../../icon/index.js";
11
11
  export let field;
12
12
  let dropDown;
13
+ let rangePicker;
13
14
  const initialValue = jsonParse(
14
15
  $page.url.searchParams.get(field.key),
15
16
  {}
@@ -41,6 +42,7 @@ function handleSubmit() {
41
42
  function handleReset() {
42
43
  dropDown.hide();
43
44
  range = { start: null, end: null };
45
+ rangePicker.clear();
44
46
  goto($urlParam.without(field.key, "skip", "take"), { replaceState: true, noScroll: true });
45
47
  }
46
48
  </script>
@@ -72,7 +74,7 @@ function handleReset() {
72
74
  on:submit|preventDefault={handleSubmit}
73
75
  data-sveltekit-replacestate
74
76
  >
75
- <RangePicker numberOfMonths={1} bind:range />
77
+ <RangePicker bind:this={rangePicker} numberOfMonths={1} bind:range />
76
78
 
77
79
  <input class="hidden" type="text" name="start" value={range.start?.toJSON()} />
78
80
  <input class="hidden" type="text" name="end" value={range.end?.toJSON()} />
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fuma",
3
- "version": "0.4.4",
3
+ "version": "0.4.6",
4
4
  "description": "My fullstack material build with sveltekit, daisyui, zod, prisma, lucia",
5
5
  "author": {
6
6
  "name": "Jonas Voisard",