simplesvelte 2.5.1 → 2.6.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/Grid.svelte CHANGED
@@ -1,168 +1,168 @@
1
- <script lang="ts">
2
- import { onMount } from 'svelte'
3
- import { env } from '$env/dynamic/public'
4
- import {
5
- AllEnterpriseModule,
6
- ClientSideRowModelModule,
7
- createGrid,
8
- LicenseManager,
9
- ModuleRegistry,
10
- themeQuartz,
11
- type GridApi,
12
- type GridOptions,
13
- } from 'ag-grid-enterprise'
14
-
15
- type Props = {
16
- gridEl?: HTMLDivElement
17
- /** Bindable reference to the AG Grid API. Use `bind:gridApi` on the parent. */
18
- gridApi?: GridApi
19
- gridData?: any[] // Replace with your actual data type
20
- gridOptions: GridOptions
21
- /**
22
- * localStorage key for automatic grid state persistence (filters, sorts, column widths).
23
- * When set, state is saved on every change and restored on mount.
24
- */
25
- stateKey?: string
26
- class?: string
27
- }
28
- let {
29
- gridEl = $bindable(),
30
- gridApi = $bindable(),
31
- gridData,
32
- gridOptions,
33
- stateKey,
34
- class: gridClass = 'grow',
35
- }: Props = $props()
36
- let initCheckInterval: ReturnType<typeof setInterval> | undefined
37
- let attemptCount = 0
38
-
39
- function initializeGrid() {
40
- if (!gridEl) {
41
- console.log('⏳ Grid: Element not available yet')
42
- return
43
- }
44
-
45
- if (gridApi) {
46
- console.log('ℹ️ Grid: Already initialized, skipping')
47
- return
48
- }
49
-
50
- attemptCount++
51
- console.log(`📊 Grid: Initializing AG Grid (attempt ${attemptCount})...`)
52
- console.log('📋 Grid: Registering modules...')
53
- ModuleRegistry.registerModules([AllEnterpriseModule, ClientSideRowModelModule])
54
-
55
- if (env.PUBLIC_AGGRID_KEY) {
56
- LicenseManager.setLicenseKey(env.PUBLIC_AGGRID_KEY)
57
- console.log('✅ Grid: License key applied successfully')
58
- } else {
59
- console.warn('⚠️ Grid: No license key found. Running in trial mode.')
60
- }
61
-
62
- // Wrap onGridReady to expose the gridApi bindable and handle stateKey persistence,
63
- // while still calling the user's own onGridReady callback if provided.
64
- const userOnGridReady = gridOptions.onGridReady
65
-
66
- // Load saved state upfront — must be in gridConfig.initialState, not applied post-init.
67
- let savedState: object | undefined
68
- if (stateKey) {
69
- try {
70
- const raw = localStorage.getItem(stateKey)
71
- if (raw) savedState = JSON.parse(raw)
72
- } catch {
73
- /* ignore parse errors */
74
- }
75
- }
76
-
77
- const gridConfig = {
78
- ...gridOptions,
79
- theme: themeQuartz,
80
- ...(gridData !== undefined && { rowData: gridData }),
81
- ...(savedState !== undefined && { initialState: savedState }),
82
- onGridReady: (params: Parameters<NonNullable<GridOptions['onGridReady']>>[0]) => {
83
- userOnGridReady?.(params)
84
- gridApi = params.api
85
- if (stateKey) {
86
- params.api.addEventListener('stateUpdated', (e: any) => {
87
- try {
88
- localStorage.setItem(stateKey, JSON.stringify(e.state))
89
- } catch {
90
- /* ignore storage errors */
91
- }
92
- })
93
- }
94
- },
95
- }
96
-
97
- console.log('🎨 Grid: Creating grid instance...')
98
- gridApi = createGrid(gridEl, gridConfig)
99
-
100
- if (gridData !== undefined) {
101
- const rowCount = gridData.length
102
- console.log(`✅ Grid: Initialized with ${rowCount} row(s) (client-side)`)
103
- } else {
104
- console.log('✅ Grid: Initialized with server-side data source')
105
- }
106
-
107
- // Clear the interval once grid is created
108
- if (initCheckInterval) {
109
- console.log('⏹️ Grid: Stopping initialization checks')
110
- clearInterval(initCheckInterval)
111
- initCheckInterval = undefined
112
- }
113
- }
114
-
115
- onMount(() => {
116
- console.log('🚀 Grid: Component mounted')
117
-
118
- // Try to initialize immediately
119
- initializeGrid()
120
-
121
- // If grid wasn't created, set up interval to keep checking
122
- if (!gridApi) {
123
- console.log('⏱️ Grid: Element not ready, checking every 100ms...')
124
- initCheckInterval = setInterval(() => {
125
- initializeGrid()
126
- }, 100)
127
- }
128
-
129
- // Cleanup function to destroy grid and clear interval when component unmounts
130
- return () => {
131
- console.log('💥 Grid: Component unmounting')
132
- if (initCheckInterval) {
133
- console.log('⏹️ Grid: Clearing initialization interval')
134
- clearInterval(initCheckInterval)
135
- initCheckInterval = undefined
136
- }
137
- if (gridApi) {
138
- console.log('🧹 Grid: Destroying grid instance')
139
- gridApi.destroy()
140
- gridApi = undefined
141
- console.log('✅ Grid: Cleanup complete')
142
- }
143
- }
144
- })
145
-
146
- // Update grid when options or data change
147
- $effect(() => {
148
- if (gridApi && gridData !== undefined) {
149
- const rowCount = gridData.length
150
- console.log(`🔄 Grid: Data changed, updating grid with ${rowCount} row(s)`)
151
-
152
- try {
153
- gridApi.updateGridOptions({
154
- ...gridOptions,
155
- rowData: gridData,
156
- })
157
- gridApi.refreshCells()
158
- console.log('✅ Grid: Data update complete')
159
- } catch (error) {
160
- console.error('❌ Grid: Error updating data:', error)
161
- }
162
- } else if (!gridApi && gridData !== undefined) {
163
- console.log('⚠️ Grid: Data available but grid not initialized yet')
164
- }
165
- })
166
- </script>
167
-
168
- <div bind:this={gridEl} class={gridClass}></div>
1
+ <script lang="ts">
2
+ import { onMount } from 'svelte'
3
+ import { env } from '$env/dynamic/public'
4
+ import {
5
+ AllEnterpriseModule,
6
+ ClientSideRowModelModule,
7
+ createGrid,
8
+ LicenseManager,
9
+ ModuleRegistry,
10
+ themeQuartz,
11
+ type GridApi,
12
+ type GridOptions,
13
+ } from 'ag-grid-enterprise'
14
+
15
+ type Props = {
16
+ gridEl?: HTMLDivElement
17
+ /** Bindable reference to the AG Grid API. Use `bind:gridApi` on the parent. */
18
+ gridApi?: GridApi
19
+ gridData?: any[] // Replace with your actual data type
20
+ gridOptions: GridOptions
21
+ /**
22
+ * localStorage key for automatic grid state persistence (filters, sorts, column widths).
23
+ * When set, state is saved on every change and restored on mount.
24
+ */
25
+ stateKey?: string
26
+ class?: string
27
+ }
28
+ let {
29
+ gridEl = $bindable(),
30
+ gridApi = $bindable(),
31
+ gridData,
32
+ gridOptions,
33
+ stateKey,
34
+ class: gridClass = 'grow',
35
+ }: Props = $props()
36
+ let initCheckInterval: ReturnType<typeof setInterval> | undefined
37
+ let attemptCount = 0
38
+
39
+ function initializeGrid() {
40
+ if (!gridEl) {
41
+ console.log('⏳ Grid: Element not available yet')
42
+ return
43
+ }
44
+
45
+ if (gridApi) {
46
+ console.log('ℹ️ Grid: Already initialized, skipping')
47
+ return
48
+ }
49
+
50
+ attemptCount++
51
+ console.log(`📊 Grid: Initializing AG Grid (attempt ${attemptCount})...`)
52
+ console.log('📋 Grid: Registering modules...')
53
+ ModuleRegistry.registerModules([AllEnterpriseModule, ClientSideRowModelModule])
54
+
55
+ if (env.PUBLIC_AGGRID_KEY) {
56
+ LicenseManager.setLicenseKey(env.PUBLIC_AGGRID_KEY)
57
+ console.log('✅ Grid: License key applied successfully')
58
+ } else {
59
+ console.warn('⚠️ Grid: No license key found. Running in trial mode.')
60
+ }
61
+
62
+ // Wrap onGridReady to expose the gridApi bindable and handle stateKey persistence,
63
+ // while still calling the user's own onGridReady callback if provided.
64
+ const userOnGridReady = gridOptions.onGridReady
65
+
66
+ // Load saved state upfront — must be in gridConfig.initialState, not applied post-init.
67
+ let savedState: object | undefined
68
+ if (stateKey) {
69
+ try {
70
+ const raw = localStorage.getItem(stateKey)
71
+ if (raw) savedState = JSON.parse(raw)
72
+ } catch {
73
+ /* ignore parse errors */
74
+ }
75
+ }
76
+
77
+ const gridConfig = {
78
+ ...gridOptions,
79
+ theme: themeQuartz,
80
+ ...(gridData !== undefined && { rowData: gridData }),
81
+ ...(savedState !== undefined && { initialState: savedState }),
82
+ onGridReady: (params: Parameters<NonNullable<GridOptions['onGridReady']>>[0]) => {
83
+ userOnGridReady?.(params)
84
+ gridApi = params.api
85
+ if (stateKey) {
86
+ params.api.addEventListener('stateUpdated', (e: any) => {
87
+ try {
88
+ localStorage.setItem(stateKey, JSON.stringify(e.state))
89
+ } catch {
90
+ /* ignore storage errors */
91
+ }
92
+ })
93
+ }
94
+ },
95
+ }
96
+
97
+ console.log('🎨 Grid: Creating grid instance...')
98
+ gridApi = createGrid(gridEl, gridConfig)
99
+
100
+ if (gridData !== undefined) {
101
+ const rowCount = gridData.length
102
+ console.log(`✅ Grid: Initialized with ${rowCount} row(s) (client-side)`)
103
+ } else {
104
+ console.log('✅ Grid: Initialized with server-side data source')
105
+ }
106
+
107
+ // Clear the interval once grid is created
108
+ if (initCheckInterval) {
109
+ console.log('⏹️ Grid: Stopping initialization checks')
110
+ clearInterval(initCheckInterval)
111
+ initCheckInterval = undefined
112
+ }
113
+ }
114
+
115
+ onMount(() => {
116
+ console.log('🚀 Grid: Component mounted')
117
+
118
+ // Try to initialize immediately
119
+ initializeGrid()
120
+
121
+ // If grid wasn't created, set up interval to keep checking
122
+ if (!gridApi) {
123
+ console.log('⏱️ Grid: Element not ready, checking every 100ms...')
124
+ initCheckInterval = setInterval(() => {
125
+ initializeGrid()
126
+ }, 100)
127
+ }
128
+
129
+ // Cleanup function to destroy grid and clear interval when component unmounts
130
+ return () => {
131
+ console.log('💥 Grid: Component unmounting')
132
+ if (initCheckInterval) {
133
+ console.log('⏹️ Grid: Clearing initialization interval')
134
+ clearInterval(initCheckInterval)
135
+ initCheckInterval = undefined
136
+ }
137
+ if (gridApi) {
138
+ console.log('🧹 Grid: Destroying grid instance')
139
+ gridApi.destroy()
140
+ gridApi = undefined
141
+ console.log('✅ Grid: Cleanup complete')
142
+ }
143
+ }
144
+ })
145
+
146
+ // Update grid when options or data change
147
+ $effect(() => {
148
+ if (gridApi && gridData !== undefined) {
149
+ const rowCount = gridData.length
150
+ console.log(`🔄 Grid: Data changed, updating grid with ${rowCount} row(s)`)
151
+
152
+ try {
153
+ gridApi.updateGridOptions({
154
+ ...gridOptions,
155
+ rowData: gridData,
156
+ })
157
+ gridApi.refreshCells()
158
+ console.log('✅ Grid: Data update complete')
159
+ } catch (error) {
160
+ console.error('❌ Grid: Error updating data:', error)
161
+ }
162
+ } else if (!gridApi && gridData !== undefined) {
163
+ console.log('⚠️ Grid: Data available but grid not initialized yet')
164
+ }
165
+ })
166
+ </script>
167
+
168
+ <div bind:this={gridEl} class={gridClass}></div>
package/dist/Input.svelte CHANGED
@@ -1,145 +1,145 @@
1
- <script lang="ts">
2
- import { SvelteDate } from 'svelte/reactivity'
3
- import Label from './Label.svelte'
4
- type Props = {
5
- value?: any
6
- name?: string
7
- label?: string
8
- class?: string
9
- required?: boolean
10
- disabled?: boolean
11
- element?: HTMLElement
12
- type?:
13
- | 'text'
14
- | 'number'
15
- | 'password'
16
- | 'email'
17
- | 'number'
18
- | 'tel'
19
- | 'url'
20
- | 'date'
21
- | 'datetime-local'
22
- | 'color'
23
- | 'file'
24
- | 'checkbox'
25
- error?: string
26
- hideOptional?: boolean
27
- zodErrors?: {
28
- expected: string
29
- code: string
30
- path: string[]
31
- message: string
32
- }[]
33
- [x: string]: any
34
- }
35
- let {
36
- value = $bindable(),
37
- element = $bindable(),
38
- label,
39
- type = 'text',
40
- name,
41
- required,
42
- disabled,
43
- class: myClass,
44
- error,
45
- hideOptional,
46
- zodErrors,
47
- ...rest
48
- }: Props = $props()
49
- function getValue() {
50
- if (type == 'date') {
51
- if (!value) return ''
52
- const dateString = new Date(value).toISOString().split('T')[0]
53
- return dateString
54
- } else if (type == 'datetime-local') {
55
- if (!value) return ''
56
- const date = new Date(value)
57
- const dateString = new Date(date.getTime() - date.getTimezoneOffset() * 60000).toISOString().slice(0, -1)
58
- return dateString
59
- }
60
- return value ?? ''
61
- }
62
- function setValue(newValue: any) {
63
- if (type == 'number') {
64
- if (isNaN(Number(newValue))) {
65
- value = null
66
- } else {
67
- value = Number(newValue)
68
- }
69
- } else if (type == 'date') {
70
- const date = new SvelteDate(newValue)
71
- if (isNaN(date.getTime())) {
72
- value = null
73
- } else {
74
- date.setUTCHours(0, 0, 0, 0)
75
- value = date
76
- }
77
- } else if (type == 'datetime-local') {
78
- const date = new SvelteDate(newValue)
79
- if (isNaN(date.getTime())) {
80
- value = null
81
- } else {
82
- date.setSeconds(0, 0)
83
- value = date
84
- }
85
- } else {
86
- value = newValue
87
- }
88
- }
89
-
90
- // File input handlers - FileList is readonly
91
- function getFiles() {
92
- return value
93
- }
94
- function setFiles(fileList: FileList | null) {
95
- // FileList is readonly, so we just set it directly
96
- value = fileList
97
- }
98
-
99
- let inputClass = $derived.by(() => {
100
- if (type == 'file') return 'file-input w-full'
101
- if (type == 'checkbox') return 'checkbox checkbox-lg'
102
- return 'input w-full'
103
- })
104
-
105
- let showOptional = $derived.by(() => {
106
- if (hideOptional) return false
107
- return !required && !disabled && type != 'checkbox'
108
- })
109
-
110
- const errorText = $derived.by(() => {
111
- if (error) return error
112
- if (!name) return undefined
113
- if (zodErrors) return zodErrors.find((e) => e.path.includes(name))?.message
114
- return undefined
115
- })
116
- </script>
117
-
118
- {#if type != 'file'}
119
- <input type="hidden" {name} value={value ?? ''} />
120
- {/if}
121
-
122
- <Label class={myClass} {label} {name} optional={showOptional} {disabled} error={errorText}>
123
- {#if type == 'checkbox'}
124
- <input bind:this={element} type="checkbox" {disabled} class={inputClass} {...rest} bind:checked={value} />
125
- {:else if type == 'file'}
126
- <input
127
- bind:this={element}
128
- {name}
129
- type="file"
130
- {disabled}
131
- {required}
132
- class={inputClass}
133
- {...rest}
134
- bind:files={getFiles, setFiles} />
135
- {:else}
136
- <input
137
- bind:this={element}
138
- {type}
139
- {disabled}
140
- {required}
141
- class="disabled:text-base-content disabled:!border-base-content/20 {inputClass} "
142
- {...rest}
143
- bind:value={getValue, setValue} />
144
- {/if}
145
- </Label>
1
+ <script lang="ts">
2
+ import { SvelteDate } from 'svelte/reactivity'
3
+ import Label from './Label.svelte'
4
+ type Props = {
5
+ value?: any
6
+ name?: string
7
+ label?: string
8
+ class?: string
9
+ required?: boolean
10
+ disabled?: boolean
11
+ element?: HTMLElement
12
+ type?:
13
+ | 'text'
14
+ | 'number'
15
+ | 'password'
16
+ | 'email'
17
+ | 'number'
18
+ | 'tel'
19
+ | 'url'
20
+ | 'date'
21
+ | 'datetime-local'
22
+ | 'color'
23
+ | 'file'
24
+ | 'checkbox'
25
+ error?: string
26
+ hideOptional?: boolean
27
+ zodErrors?: {
28
+ expected: string
29
+ code: string
30
+ path: string[]
31
+ message: string
32
+ }[]
33
+ [x: string]: any
34
+ }
35
+ let {
36
+ value = $bindable(),
37
+ element = $bindable(),
38
+ label,
39
+ type = 'text',
40
+ name,
41
+ required,
42
+ disabled,
43
+ class: myClass,
44
+ error,
45
+ hideOptional,
46
+ zodErrors,
47
+ ...rest
48
+ }: Props = $props()
49
+ function getValue() {
50
+ if (type == 'date') {
51
+ if (!value) return ''
52
+ const dateString = new Date(value).toISOString().split('T')[0]
53
+ return dateString
54
+ } else if (type == 'datetime-local') {
55
+ if (!value) return ''
56
+ const date = new Date(value)
57
+ const dateString = new Date(date.getTime() - date.getTimezoneOffset() * 60000).toISOString().slice(0, -1)
58
+ return dateString
59
+ }
60
+ return value ?? ''
61
+ }
62
+ function setValue(newValue: any) {
63
+ if (type == 'number') {
64
+ if (isNaN(Number(newValue))) {
65
+ value = null
66
+ } else {
67
+ value = Number(newValue)
68
+ }
69
+ } else if (type == 'date') {
70
+ const date = new SvelteDate(newValue)
71
+ if (isNaN(date.getTime())) {
72
+ value = null
73
+ } else {
74
+ date.setUTCHours(0, 0, 0, 0)
75
+ value = date
76
+ }
77
+ } else if (type == 'datetime-local') {
78
+ const date = new SvelteDate(newValue)
79
+ if (isNaN(date.getTime())) {
80
+ value = null
81
+ } else {
82
+ date.setSeconds(0, 0)
83
+ value = date
84
+ }
85
+ } else {
86
+ value = newValue
87
+ }
88
+ }
89
+
90
+ // File input handlers - FileList is readonly
91
+ function getFiles() {
92
+ return value
93
+ }
94
+ function setFiles(fileList: FileList | null) {
95
+ // FileList is readonly, so we just set it directly
96
+ value = fileList
97
+ }
98
+
99
+ let inputClass = $derived.by(() => {
100
+ if (type == 'file') return 'file-input w-full'
101
+ if (type == 'checkbox') return 'checkbox checkbox-lg'
102
+ return 'input w-full'
103
+ })
104
+
105
+ let showOptional = $derived.by(() => {
106
+ if (hideOptional) return false
107
+ return !required && !disabled && type != 'checkbox'
108
+ })
109
+
110
+ const errorText = $derived.by(() => {
111
+ if (error) return error
112
+ if (!name) return undefined
113
+ if (zodErrors) return zodErrors.find((e) => e.path.includes(name))?.message
114
+ return undefined
115
+ })
116
+ </script>
117
+
118
+ {#if type != 'file'}
119
+ <input type="hidden" {name} value={value ?? ''} />
120
+ {/if}
121
+
122
+ <Label class={myClass} {label} {name} optional={showOptional} {disabled} error={errorText}>
123
+ {#if type == 'checkbox'}
124
+ <input bind:this={element} type="checkbox" {disabled} class={inputClass} {...rest} bind:checked={value} />
125
+ {:else if type == 'file'}
126
+ <input
127
+ bind:this={element}
128
+ {name}
129
+ type="file"
130
+ {disabled}
131
+ {required}
132
+ class={inputClass}
133
+ {...rest}
134
+ bind:files={getFiles, setFiles} />
135
+ {:else}
136
+ <input
137
+ bind:this={element}
138
+ {type}
139
+ {disabled}
140
+ {required}
141
+ class="disabled:text-base-content disabled:!border-base-content/20 {inputClass} "
142
+ {...rest}
143
+ bind:value={getValue, setValue} />
144
+ {/if}
145
+ </Label>