sveltacular 0.0.43 → 0.0.44

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.
@@ -2,7 +2,7 @@
2
2
  const dispatch = createEventDispatcher();
3
3
  export let title = void 0;
4
4
  export let style = "info";
5
- export let size = "full";
5
+ export let size = "md";
6
6
  export let dismissable = false;
7
7
  let visible = true;
8
8
  let fading = false;
@@ -54,9 +54,9 @@ const onClick = (e) => {
54
54
  max-width: 100%;
55
55
  padding: 1rem;
56
56
  border-radius: 0.2rem;
57
- border: 2px solid var(--base-fg, black);
58
- background: var(--base-bg, white);
59
- color: var(--base-fg, black);
57
+ border: 2px solid var(--base-bg, black);
58
+ background: var(--base-fg, white);
59
+ color: var(--base-bg, black);
60
60
  position: relative;
61
61
  opacity: 1;
62
62
  transition: opacity 0.3s ease-in-out, transform 0.5s ease-in-out;
@@ -101,11 +101,12 @@ const onClick = (e) => {
101
101
  color: rgb(100, 0, 0);
102
102
  border-color: rgb(218, 40, 40);
103
103
  }
104
- .notice.xl {
105
- width: 60rem;
104
+ .notice.xl .icon {
105
+ width: 3rem;
106
+ min-width: 3rem;
106
107
  }
107
- .notice.lg {
108
- width: 40rem;
108
+ .notice.xl .content {
109
+ font-size: 1.15rem;
109
110
  }
110
111
  .notice.lg .icon {
111
112
  width: 2.5rem;
@@ -115,7 +116,6 @@ const onClick = (e) => {
115
116
  font-size: 0.95rem;
116
117
  }
117
118
  .notice.md {
118
- width: 25rem;
119
119
  border-width: 1px;
120
120
  border-radius: 3px;
121
121
  }
@@ -127,7 +127,6 @@ const onClick = (e) => {
127
127
  font-size: 0.85rem;
128
128
  }
129
129
  .notice.sm {
130
- width: 15rem;
131
130
  border-width: 1px;
132
131
  border-radius: 2px;
133
132
  }
@@ -3,7 +3,7 @@ declare const __propDef: {
3
3
  props: {
4
4
  title?: string | undefined;
5
5
  style?: ("outline" | "attention" | "success" | "error" | "info") | undefined;
6
- size?: ("sm" | "md" | "lg" | "xl" | "full") | undefined;
6
+ size?: ("sm" | "md" | "lg" | "xl") | undefined;
7
7
  dismissable?: boolean | undefined;
8
8
  };
9
9
  events: {
@@ -2,6 +2,8 @@
2
2
  export let currentPage = 1;
3
3
  export let totalPages = 1;
4
4
  export let align = "center";
5
+ export let style = "default";
6
+ export let size = "md";
5
7
  const dispatch = createEventDispatcher();
6
8
  const changePage = (page) => {
7
9
  if (page < 1 || page > totalPages)
@@ -31,79 +33,97 @@ $:
31
33
  showLast = currentPage < totalPages - 3;
32
34
  </script>
33
35
 
34
- <nav class={align}>
36
+ <nav class="{align} {style} {size}">
35
37
  {#if currentPage > 1}
36
- <button on:click={() => changePage(currentPage - 1)} class="previous">Previous</button>
38
+ <button on:click={() => changePage(currentPage - 1)} class="previous page">Previous</button>
37
39
  {/if}
38
40
  {#if showFirst}
39
- <button on:click={() => changePage(1)} class="first">1</button>
40
- <div class="ellipsis">...</div>
41
+ <button on:click={() => changePage(1)} class="first page">1</button>
42
+ <div class="ellipsis page">···</div>
41
43
  {/if}
42
44
  {#each previousPages as page}
43
- <button on:click={() => changePage(page)}>{page}</button>
45
+ <button on:click={() => changePage(page)} class="pre page">{page}</button>
44
46
  {/each}
45
- <div class="current">{currentPage}</div>
47
+ <div class="current page">{currentPage}</div>
46
48
  {#each nextPages as page}
47
- <button on:click={() => changePage(page)}>{page}</button>
49
+ <button on:click={() => changePage(page)} class="pro numbered page">{page}</button>
48
50
  {/each}
49
51
  {#if showLast}
50
- <div class="ellipsis">...</div>
51
- <button on:click={() => changePage(totalPages)} class="last">{totalPages}</button>
52
+ <div class="ellipsis page">···</div>
53
+ <button on:click={() => changePage(totalPages)} class="last page">{totalPages}</button>
52
54
  {/if}
53
55
  {#if currentPage < totalPages}
54
- <button on:click={() => changePage(currentPage + 1)} class="next">Next</button>
56
+ <button on:click={() => changePage(currentPage + 1)} class="next page">Next</button>
55
57
  {/if}
56
58
  </nav>
57
59
 
58
60
  <style>nav {
59
61
  display: flex;
62
+ flex-direction: row;
63
+ gap: 0.2rem;
60
64
  align-items: center;
61
65
  justify-content: center;
62
- gap: 0rem;
63
66
  }
64
- nav button {
65
- appearance: none;
66
- padding-left: 1rem;
67
- padding-right: 1rem;
68
- font-size: 1rem;
69
- line-height: 1.4rem;
70
- height: 1.5rem;
67
+ nav .page {
71
68
  border: none;
72
- cursor: pointer;
73
- background-color: var(--form-input-background, white);
74
- color: var(--form-input-text, black);
75
- }
76
- nav button:hover {
77
- background-color: var(--form-input-border, black);
78
- color: var(--form-input-background, white);
69
+ background: none;
70
+ margin: 0;
71
+ color: var(--base-fg, #ccc);
72
+ text-shadow: 0 0 0.125rem rgba(0, 0, 0, 0.5);
79
73
  }
80
- nav button.previous {
81
- border-radius: 0.5rem 0 0 0.5rem;
82
- border-right: solid 1px var(--form-input-border, black);
83
- }
84
- nav button.next {
85
- border-radius: 0 0.5rem 0.5rem 0;
86
- border-left: solid 1px var(--form-input-border, black);
87
- }
88
- nav .ellipsis {
89
- height: 1.5rem;
90
- font-size: 1rem;
91
- line-height: 1rem;
92
- padding-left: 0.1rem;
93
- padding-right: 0.1rem;
94
- background-color: var(--form-input-background, white);
95
- color: var(--form-input-text, black);
74
+ nav button {
75
+ cursor: pointer;
96
76
  }
97
77
  nav .current {
98
- padding: 0.5rem 1rem;
99
- border: 1px solid var(--form-input-border, black);
100
- border-radius: 0.5rem;
101
- background-color: var(--form-input-background, white);
102
- color: var(--form-input-text, black);
78
+ font-weight: 700;
103
79
  }
104
80
  nav.start {
105
81
  justify-content: flex-start;
106
82
  }
107
83
  nav.end {
108
84
  justify-content: flex-end;
85
+ }
86
+ nav.sm .page {
87
+ font-size: 0.75rem;
88
+ padding: 0.5rem 0.65rem 0.5rem 0.65rem;
89
+ }
90
+ nav.sm .current {
91
+ font-size: 0.95rem;
92
+ }
93
+ nav.md .page {
94
+ font-size: 0.85rem;
95
+ padding: 0.5rem 0.65rem 0.5rem 0.65rem;
96
+ }
97
+ nav.md .current {
98
+ font-size: 1.05rem;
99
+ }
100
+ nav.lg .page {
101
+ font-size: 0.95rem;
102
+ padding: 0.5rem 0.65rem 0.5rem 0.65rem;
103
+ }
104
+ nav.lg .current {
105
+ font-size: 1.15rem;
106
+ }
107
+ nav.xl .page {
108
+ font-size: 1.05rem;
109
+ padding: 0.5rem 0.65rem 0.5rem 0.65rem;
110
+ }
111
+ nav.xl .current {
112
+ font-size: 1.25rem;
113
+ }
114
+
115
+ nav.flat button:hover {
116
+ color: var(--form-input-bg, #fff);
117
+ background: var(--form-input-fg, #000);
118
+ border-radius: 0.5rem;
119
+ }
120
+
121
+ @media (max-width: 600px) {
122
+ nav {
123
+ gap: 0rem;
124
+ }
125
+ nav .pre,
126
+ nav .pro {
127
+ display: none;
128
+ }
109
129
  }</style>
@@ -4,6 +4,8 @@ declare const __propDef: {
4
4
  currentPage?: number | undefined;
5
5
  totalPages?: number | undefined;
6
6
  align?: "center" | "end" | "start" | undefined;
7
+ style?: "default" | "flat" | undefined;
8
+ size?: "sm" | "md" | "lg" | "xl" | undefined;
7
9
  };
8
10
  events: {
9
11
  page: CustomEvent<number>;
@@ -1,4 +1,4 @@
1
- <script>import { getContext, onDestroy } from "svelte";
1
+ <script>import { getContext } from "svelte";
2
2
  import Notice from "../../generic/notice/notice.svelte";
3
3
  const wizard = getContext("wizard");
4
4
  const state = wizard.state;
@@ -14,9 +14,7 @@ $:
14
14
  <div class="step {isCurrentStep ? 'current' : ''}">
15
15
  {#if errors.length}
16
16
  <div class="errors">
17
- {#each errors as error}
18
- <Notice style="error">{error}</Notice>
19
- {/each}
17
+ <Notice style="error" size="md">{errors.join(' ')}</Notice>
20
18
  </div>
21
19
  {/if}
22
20
  <slot />
@@ -40,9 +40,11 @@ const validate = async (callback) => {
40
40
  const next = async () => {
41
41
  if (currentStep >= Object.values(steps).length || disabled)
42
42
  return;
43
- const errors2 = await validate(() => onNext(currentStep));
44
- if (errors2.length)
45
- return publish();
43
+ if (currentStep) {
44
+ const errors2 = await validate(() => onNext(currentStep));
45
+ if (errors2.length)
46
+ return publish();
47
+ }
46
48
  currentStep++;
47
49
  dispatch("next", currentStep);
48
50
  publish();
@@ -10,8 +10,8 @@ import TableRow from "./table-row.svelte";
10
10
  import Table from "./table.svelte";
11
11
  import Empty from "../generic/empty/empty.svelte";
12
12
  import FolderOpenIcon from "../icons/folder-open-icon.svelte";
13
+ import Pagination from "../navigation/pagination/pagination.svelte";
13
14
  import Loading from "../placeholders/loading.svelte";
14
- import Text from "../typography/text.svelte";
15
15
  import TableCaption from "./table-caption.svelte";
16
16
  export let caption = "";
17
17
  export let rows = void 0;
@@ -19,6 +19,7 @@ export let cols;
19
19
  export let pagination = void 0;
20
20
  export let editRow = void 0;
21
21
  export let deleteRow = void 0;
22
+ export let onPageChange = null;
22
23
  const getColType = (col) => {
23
24
  if (col.type)
24
25
  return col.type;
@@ -42,12 +43,37 @@ const format = (row, key) => {
42
43
  return col.format(row, key);
43
44
  return row[key];
44
45
  };
46
+ const calculateTotalPages = () => {
47
+ if (!pagination || !rows)
48
+ return 1;
49
+ const totalRows = Math.max(pagination.total || rows.length);
50
+ return Math.ceil(totalRows / pagination.perPage);
51
+ };
52
+ const changePage = async (e) => {
53
+ pagination = { page: e.detail, perPage: pagination?.perPage || 5 };
54
+ if (onPageChange) {
55
+ rows = await onPageChange(pagination);
56
+ }
57
+ };
58
+ const filterRows = () => {
59
+ if (!rows?.length || !pagination)
60
+ return rows;
61
+ if (onPageChange)
62
+ return rows;
63
+ const currentPage = pagination.page || 1;
64
+ const perPage = pagination.perPage || 5;
65
+ const startIndex = currentPage * perPage - perPage;
66
+ const endIndex = startIndex + perPage;
67
+ return rows.filter((_row, index) => index >= startIndex && index < endIndex);
68
+ };
45
69
  $:
46
70
  hasActionRow = editRow || deleteRow;
47
71
  $:
48
72
  colCount = Math.max(1, cols.filter((col) => !col.hide).length) + (hasActionRow ? 1 : 0);
49
73
  $:
50
- totalPages = pagination && rows ? Math.ceil((pagination.total || rows.length) / pagination.perPage) : 1;
74
+ totalPages = pagination && rows ? calculateTotalPages() : 1;
75
+ $:
76
+ filteredRows = rows && pagination ? filterRows() : rows;
51
77
  </script>
52
78
 
53
79
  <Table>
@@ -58,7 +84,7 @@ $:
58
84
  <TableHeaderRow>
59
85
  {#each cols as col}
60
86
  {#if !col.hide}
61
- <TableHeaderCell type={getColType(col)}>{col.label}</TableHeaderCell>
87
+ <TableHeaderCell type={getColType(col)} width={col.width}>{col.label}</TableHeaderCell>
62
88
  {/if}
63
89
  {/each}
64
90
  {#if hasActionRow}
@@ -67,7 +93,7 @@ $:
67
93
  </TableHeaderRow>
68
94
  </TableHeader>
69
95
  <TableBody>
70
- {#if !rows?.length}
96
+ {#if !filteredRows?.length}
71
97
  <TableRow>
72
98
  <TableCell colspan={colCount}>
73
99
  <div class="empty">
@@ -82,11 +108,11 @@ $:
82
108
  </TableCell>
83
109
  </TableRow>
84
110
  {:else}
85
- {#each rows as row}
111
+ {#each filteredRows as row}
86
112
  <TableRow>
87
113
  {#each cols as col}
88
114
  {#if !col.hide}
89
- <TableCell type={col.type || typeof row[col.key]}>
115
+ <TableCell type={col.type || typeof row[col.key]} width={col.width}>
90
116
  {#if col.link}
91
117
  <a href={col.link(row, col.key)}>{format(row, col.key)}</a>
92
118
  {:else}
@@ -113,9 +139,14 @@ $:
113
139
  <TableFooter>
114
140
  <TableFooterRow>
115
141
  <TableFooterCell colspan={colCount}>
116
- <Text transform="uppercase">
117
- Page {pagination.page} of {totalPages}
118
- </Text>
142
+ <Pagination
143
+ currentPage={pagination.page}
144
+ {totalPages}
145
+ style="flat"
146
+ size="sm"
147
+ align="center"
148
+ on:page={changePage}
149
+ />
119
150
  </TableFooterCell>
120
151
  </TableFooterRow>
121
152
  </TableFooter>
@@ -1,13 +1,16 @@
1
1
  import { SvelteComponent } from "svelte";
2
- import type { DataCol, DataRow, Pagination } from '../types/data.js';
2
+ import type { DataCol, DataRow, PaginationProperties } from '../types/data.js';
3
3
  declare const __propDef: {
4
4
  props: {
5
5
  caption?: string | undefined;
6
6
  rows?: DataRow[] | undefined;
7
7
  cols: DataCol[];
8
- pagination?: Pagination | undefined;
8
+ pagination?: PaginationProperties | undefined;
9
9
  editRow?: ((row: DataRow) => unknown) | undefined;
10
10
  deleteRow?: ((row: DataRow) => unknown) | undefined;
11
+ /**
12
+ * Handle page change, which should return the new filtered/fetched rows.
13
+ */ onPageChange?: ((pagination: PaginationProperties) => Promise<DataRow[]>) | null | undefined;
11
14
  };
12
15
  events: {
13
16
  [evt: string]: CustomEvent<any>;
@@ -1,13 +1,19 @@
1
1
  <script>export let colspan = 1;
2
2
  export let type = void 0;
3
+ export let width = void 0;
4
+ $:
5
+ styleProperties = [
6
+ `text-align: ${type === "currency" || type === "number" ? "right" : type === "boolean" ? "center" : "left"}`,
7
+ `width: ${width ? width : "auto"}`
8
+ ];
3
9
  </script>
4
10
 
5
- <td {colspan} class={type}>
11
+ <td {colspan} class={type} style={styleProperties.join('; ')}>
6
12
  <slot />
7
13
  </td>
8
14
 
9
15
  <style>td {
10
- padding: 0.5rem;
16
+ padding: 0.25rem;
11
17
  font-size: 1rem;
12
18
  }
13
19
  td.currency, td.number {
@@ -3,6 +3,7 @@ declare const __propDef: {
3
3
  props: {
4
4
  colspan?: number | undefined;
5
5
  type?: string | undefined;
6
+ width?: number | string | undefined;
6
7
  };
7
8
  events: {
8
9
  [evt: string]: CustomEvent<any>;
@@ -2,7 +2,9 @@
2
2
  </script>
3
3
 
4
4
  <td {colspan}>
5
- <slot />
5
+ <div>
6
+ <slot />
7
+ </div>
6
8
  </td>
7
9
 
8
10
  <style>
@@ -12,4 +14,10 @@
12
14
  font-family: sans-serif;
13
15
  text-shadow: 1px 1px 1px black;
14
16
  }
17
+
18
+ div {
19
+ display: flex;
20
+ justify-content: center;
21
+ align-items: center;
22
+ }
15
23
  </style>
@@ -1,8 +1,16 @@
1
1
  <script>export let colspan = 1;
2
2
  export let type = void 0;
3
+ export let width = void 0;
4
+ $:
5
+ styleProperties = [
6
+ `text-align: ${type === "currency" || type === "number" ? "right" : type === "boolean" ? "center" : "left"}`,
7
+ "text-overflow: ellipsis",
8
+ "overflow: hidden",
9
+ `width: ${width ? width : "auto"}`
10
+ ];
3
11
  </script>
4
12
 
5
- <th {colspan} class={type}>
13
+ <th {colspan} class={type} style={styleProperties.join('; ')}>
6
14
  <slot />
7
15
  </th>
8
16
 
@@ -3,6 +3,7 @@ declare const __propDef: {
3
3
  props: {
4
4
  colspan?: number | undefined;
5
5
  type?: string | undefined;
6
+ width?: number | string | undefined;
6
7
  };
7
8
  events: {
8
9
  [evt: string]: CustomEvent<any>;
@@ -6,8 +6,9 @@ export type DataCol<T extends DataRow = DataRow> = {
6
6
  format?: (row: T, key: keyof T) => string;
7
7
  link?: (row: T, key: keyof T) => string;
8
8
  hide?: boolean;
9
+ width?: number | string;
9
10
  };
10
- export type Pagination = {
11
+ export type PaginationProperties = {
11
12
  page: number;
12
13
  perPage: number;
13
14
  total?: number;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sveltacular",
3
- "version": "0.0.43",
3
+ "version": "0.0.44",
4
4
  "description": "A Svelte component library",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.js",