@txstate-mws/svelte-components 1.0.2 → 1.0.3
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 +40 -17
- package/{dist/ts/actions → actions}/buttonify.d.ts +0 -0
- package/{dist/actions → actions}/buttonify.js +1 -6
- package/{dist/ts/actions → actions}/glue.d.ts +1 -1
- package/{dist/actions → actions}/glue.js +8 -13
- package/actions/index.d.ts +7 -0
- package/actions/index.js +7 -0
- package/actions/offset.d.ts +15 -0
- package/actions/offset.js +35 -0
- package/{dist/ts/actions → actions}/portal.d.ts +0 -0
- package/actions/portal.js +13 -0
- package/{dist/ts/actions → actions}/resize.d.ts +6 -2
- package/actions/resize.js +45 -0
- package/{dist/ts/actions → actions}/sticky.d.ts +2 -2
- package/{dist/actions → actions}/sticky.js +10 -18
- package/{dist/ts/actions → actions}/stickyfixed.d.ts +2 -2
- package/{dist/actions → actions}/stickyfixed.js +14 -23
- package/{dist/components → components}/CollapsingTable.svelte +12 -13
- package/components/CollapsingTable.svelte.d.ts +59 -0
- package/{dist/ts/components → components}/ConditionalWrapper.svelte +6 -7
- package/components/ConditionalWrapper.svelte.d.ts +23 -0
- package/{dist/components → components}/FocusLock.svelte +11 -9
- package/components/FocusLock.svelte.d.ts +26 -0
- package/{dist/components → components}/Modal.svelte +5 -4
- package/components/Modal.svelte.d.ts +27 -0
- package/{dist/components → components}/PopupMenu.svelte +13 -16
- package/components/PopupMenu.svelte.d.ts +44 -0
- package/{dist/components → components}/ScreenReaderOnly.svelte +1 -1
- package/components/ScreenReaderOnly.svelte.d.ts +20 -0
- package/{dist/ts/components → components}/index.d.ts +0 -0
- package/components/index.js +6 -0
- package/index.d.ts +4 -0
- package/index.js +4 -0
- package/package.json +47 -76
- package/{dist/ts/types → types}/CollapsingTable.d.ts +0 -0
- package/{dist/ts/tests/Actions/Actions.stories.d.ts → types/CollapsingTable.js} +0 -0
- package/{dist/ts/types → types}/PopupMenu.d.ts +0 -0
- package/{dist/ts/tests/CollapsingTable/CollapsingTable.stories.d.ts → types/PopupMenu.js} +0 -0
- package/types/index.d.ts +2 -0
- package/types/index.js +2 -0
- package/{dist/ts/lib → util}/bodyoffset.d.ts +2 -1
- package/{dist/lib → util}/bodyoffset.js +10 -14
- package/util/index.d.ts +3 -0
- package/util/index.js +3 -0
- package/{dist/ts/lib → util}/repositioned.d.ts +1 -2
- package/{dist/lib → util}/repositioned.js +14 -24
- package/{dist/ts/lib → util}/util.d.ts +0 -0
- package/util/util.js +10 -0
- package/LICENSE +0 -21
- package/dist/actions/buttonify.js.map +0 -1
- package/dist/actions/glue.js.map +0 -1
- package/dist/actions/index.js +0 -20
- package/dist/actions/index.js.map +0 -1
- package/dist/actions/offset.js +0 -35
- package/dist/actions/offset.js.map +0 -1
- package/dist/actions/portal.js +0 -19
- package/dist/actions/portal.js.map +0 -1
- package/dist/actions/resize.js +0 -48
- package/dist/actions/resize.js.map +0 -1
- package/dist/actions/sticky.js.map +0 -1
- package/dist/actions/stickyfixed.js.map +0 -1
- package/dist/components/ConditionalWrapper.svelte +0 -38
- package/dist/components/index.js +0 -19
- package/dist/components/index.js.map +0 -1
- package/dist/index.js +0 -17
- package/dist/index.js.map +0 -1
- package/dist/lib/activestore.js +0 -123
- package/dist/lib/activestore.js.map +0 -1
- package/dist/lib/bodyoffset.js.map +0 -1
- package/dist/lib/convertedstore.js +0 -41
- package/dist/lib/convertedstore.js.map +0 -1
- package/dist/lib/derivedstore.js +0 -65
- package/dist/lib/derivedstore.js.map +0 -1
- package/dist/lib/index.js +0 -22
- package/dist/lib/index.js.map +0 -1
- package/dist/lib/repositioned.js.map +0 -1
- package/dist/lib/safestore.js +0 -16
- package/dist/lib/safestore.js.map +0 -1
- package/dist/lib/store.js +0 -27
- package/dist/lib/store.js.map +0 -1
- package/dist/lib/substore.js +0 -47
- package/dist/lib/substore.js.map +0 -1
- package/dist/lib/util.js +0 -16
- package/dist/lib/util.js.map +0 -1
- package/dist/ts/actions/index.d.ts +0 -7
- package/dist/ts/actions/offset.d.ts +0 -15
- package/dist/ts/components/CollapsingTable.svelte +0 -147
- package/dist/ts/components/FocusLock.svelte +0 -101
- package/dist/ts/components/Modal.svelte +0 -54
- package/dist/ts/components/PopupMenu.svelte +0 -279
- package/dist/ts/components/ScreenReaderOnly.svelte +0 -26
- package/dist/ts/index.d.ts +0 -4
- package/dist/ts/lib/activestore.d.ts +0 -60
- package/dist/ts/lib/convertedstore.d.ts +0 -16
- package/dist/ts/lib/derivedstore.d.ts +0 -23
- package/dist/ts/lib/index.d.ts +0 -9
- package/dist/ts/lib/safestore.d.ts +0 -4
- package/dist/ts/lib/store.d.ts +0 -16
- package/dist/ts/lib/substore.d.ts +0 -24
- package/dist/ts/tests/Actions/Offset.svelte +0 -34
- package/dist/ts/tests/Actions/Resize.svelte +0 -31
- package/dist/ts/tests/Actions/Sticky.svelte +0 -65
- package/dist/ts/tests/CollapsingTable/CollapsingTable.test.d.ts +0 -1
- package/dist/ts/tests/CollapsingTable/CollapsingTableTest.svelte +0 -36
- package/dist/ts/tests/Modal/Modal.stories.d.ts +0 -1
- package/dist/ts/tests/Modal/Modal.test.d.ts +0 -1
- package/dist/ts/tests/Modal/ModalTest.svelte +0 -58
- package/dist/ts/tests/PopupMenu/PopupMenu.stories.d.ts +0 -1
- package/dist/ts/tests/PopupMenu/PopupMenu.test.d.ts +0 -1
- package/dist/ts/tests/PopupMenu/PopupMenuBody.svelte +0 -34
- package/dist/ts/tests/PopupMenu/PopupMenuButtonIsParent.svelte +0 -36
- package/dist/ts/tests/PopupMenu/PopupMenuComplex.svelte +0 -34
- package/dist/ts/tests/PopupMenu/PopupMenuSimple.svelte +0 -36
- package/dist/ts/tests/stores/deepstore.test.d.ts +0 -1
- package/dist/ts/types/index.d.ts +0 -2
- package/dist/types/CollapsingTable.js +0 -3
- package/dist/types/CollapsingTable.js.map +0 -1
- package/dist/types/PopupMenu.js +0 -3
- package/dist/types/PopupMenu.js.map +0 -1
- package/dist/types/index.js +0 -15
- package/dist/types/index.js.map +0 -1
- package/docs/CollapsingTable.md +0 -79
- package/docs/ConditionalWrapper.md +0 -35
- package/docs/Modal.md +0 -63
- package/docs/PopupMenu.md +0 -31
- package/docs/ScreenReaderOnly.md +0 -10
- package/docs/actions.md +0 -84
- package/docs/stores.md +0 -203
- package/esm/index.js +0 -1
- package/esm/package.json +0 -3
package/docs/stores.md
DELETED
|
@@ -1,203 +0,0 @@
|
|
|
1
|
-
# Overview
|
|
2
|
-
A set of stores to complement svelte stores. These stores perform deep equality checks on the data before updating subscribers, and are easy to subclass and add mutation methods.
|
|
3
|
-
|
|
4
|
-
## Subclassing
|
|
5
|
-
The most effective way to use a store is to create a Store subclass with mutation
|
|
6
|
-
methods. If you're familiar with redux, these methods would be similar to actions on
|
|
7
|
-
reducers.
|
|
8
|
-
```typescript
|
|
9
|
-
interface MyState {
|
|
10
|
-
foo: string
|
|
11
|
-
more: string
|
|
12
|
-
}
|
|
13
|
-
class MyStore extends Store<MyState> {
|
|
14
|
-
updateFoo (newfoo: string) {
|
|
15
|
-
// do some business logic here
|
|
16
|
-
newfoo = newfoo.trim().toLocaleLowerCase()
|
|
17
|
-
this.set({ ...this.value, foo: newfoo })
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
const store = new MyStore({ foo: 'bar', more: 'state' })
|
|
21
|
-
store.updateFoo('baz')
|
|
22
|
-
```
|
|
23
|
-
This way your store controls all the business logic and your components can be truly
|
|
24
|
-
reactive.
|
|
25
|
-
|
|
26
|
-
Note that `this.value` contains the current version of the store. You can also use the
|
|
27
|
-
`store.update` method to have the current value passed to you.
|
|
28
|
-
|
|
29
|
-
### Asynchronous mutations
|
|
30
|
-
Mutation methods become even more powerful when you do asynchronous updates. All of
|
|
31
|
-
your asynchronous code can be encapsulated in a single method, making it much easier
|
|
32
|
-
to think about how you want to handle race conditions and errors. Redux toolkit would
|
|
33
|
-
call these `thunk` functions, but here they are just another method.
|
|
34
|
-
```typescript
|
|
35
|
-
interface BookState {
|
|
36
|
-
loading?: boolean
|
|
37
|
-
book?: Book
|
|
38
|
-
error?: string
|
|
39
|
-
}
|
|
40
|
-
class BookStore extends Store<BookState> {
|
|
41
|
-
async getBook (id: number) {
|
|
42
|
-
if (this.value.loading) return // one book at a time!
|
|
43
|
-
this.set({ loading: true, book: undefined, error: undefined })
|
|
44
|
-
try {
|
|
45
|
-
const book = await api.getBook(id)
|
|
46
|
-
this.set({ loading: false, book, error: undefined })
|
|
47
|
-
} catch (e) {
|
|
48
|
-
this.set({ loading: false, book: undefined, error: e.message })
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
### Creating and sharing store instances
|
|
55
|
-
It's up to you to determine how you'd like to create and share stores. The singleton
|
|
56
|
-
pattern works great for end user applications. For instance, a global error store can
|
|
57
|
-
help individual components communicate with the layout component when they experience
|
|
58
|
-
a problem that's fatal for the page. Creating a singleton store for each screen in your
|
|
59
|
-
application is another powerful pattern and helps all your components share the screen
|
|
60
|
-
state.
|
|
61
|
-
|
|
62
|
-
Context can be very convenient as well. The main benefit of putting a store in Context
|
|
63
|
-
is it can be garbage collected when the context owner is unmounted. In SSR scenarios,
|
|
64
|
-
global stores can leak between clients unless you're careful to reset them on each request,
|
|
65
|
-
so storing in Context can be safer.
|
|
66
|
-
|
|
67
|
-
Similarly, a store can be created in a component and passed down as a prop, enabling
|
|
68
|
-
efficient two-way communication with its children. The main advantage over binding a
|
|
69
|
-
property is that the components can share the mutation methods.
|
|
70
|
-
|
|
71
|
-
## Store Types
|
|
72
|
-
|
|
73
|
-
### Store
|
|
74
|
-
This is the basic store type and performs deep equality checks before notifying subscribers.
|
|
75
|
-
It is intended to contain simple JSON state that is easy to programmatically explore. By
|
|
76
|
-
default, you are expected to update the store with fresh or cloned objects:
|
|
77
|
-
```typescript
|
|
78
|
-
const initialState = { foo: 'bar', more: 'state' }
|
|
79
|
-
const store = new Store(initialState)
|
|
80
|
-
store.update(state => ({ ...state, foo: 'baz' }))
|
|
81
|
-
```
|
|
82
|
-
### SafeStore
|
|
83
|
-
If it's not convenient to clone your objects, you can use a `SafeStore` instead,
|
|
84
|
-
which will allow you to mutate your state and then call `set` on it:
|
|
85
|
-
```typescript
|
|
86
|
-
const initialState = { foo: 'bar', more: 'state' }
|
|
87
|
-
const store = new SafeStore(initialState)
|
|
88
|
-
initialState.foo = 'baz'
|
|
89
|
-
store.set(initialState) // with a regular Store, this would not notify subscribers
|
|
90
|
-
```
|
|
91
|
-
This is only designed to work on pure JSON (objects and arrays, not Maps, Sets, or
|
|
92
|
-
any other data types). There is a slight performance cost due to deep cloning.
|
|
93
|
-
|
|
94
|
-
### ActiveStore
|
|
95
|
-
This is a store that does no equality checks before notifying subscribers. It can save a couple
|
|
96
|
-
CPU cycles by skipping the deep equality check, but may be an overall performance degradation
|
|
97
|
-
if subscribers are doing significant work and there are many updates that do not change the state.
|
|
98
|
-
It is also vulnerable to unexpected infinite loops if subscribers end up triggering a redundant
|
|
99
|
-
`set` command. This store is safe to use with mutated objects and is the only one that can
|
|
100
|
-
handle non-JSON objects in the state.
|
|
101
|
-
|
|
102
|
-
### SubStore
|
|
103
|
-
This is a store that makes it convenient to interact with a portion of a larger store. You
|
|
104
|
-
subscribe to a parent store in the constructor, and when you update the SubStore, your
|
|
105
|
-
changes will be sent to the parent store.
|
|
106
|
-
|
|
107
|
-
#### Getter / Setter version of SubStore
|
|
108
|
-
This requires both a getter and setter function to handle each direction. The setter is given
|
|
109
|
-
the new SubStore state and the existing parent store state and should return a new state for
|
|
110
|
-
the parent store.
|
|
111
|
-
```typescript
|
|
112
|
-
const parentStore = new Store({
|
|
113
|
-
about: { header: 'About' },
|
|
114
|
-
events: { header: 'Events' }
|
|
115
|
-
})
|
|
116
|
-
const aboutStore = new SubStore(parentStore, pState => pState.about, (newAboutState, pState) => ({ ...pState, about: newAboutState }))
|
|
117
|
-
aboutStore.set({ header: 'About Us' })
|
|
118
|
-
// aboutStore state is { header: 'About Us' }
|
|
119
|
-
// parentStore state is { about: { header: 'About Us' }, events: { header: 'Events' } }
|
|
120
|
-
```
|
|
121
|
-
|
|
122
|
-
#### Accessor string version of SubStore
|
|
123
|
-
Alternatively, a dot-prop accessor string can be provided and both the getter and setter will be
|
|
124
|
-
automatically generated.
|
|
125
|
-
```typescript
|
|
126
|
-
const parentStore = new Store({
|
|
127
|
-
about: { header: 'About' },
|
|
128
|
-
events: { header: 'Events' }
|
|
129
|
-
})
|
|
130
|
-
const aboutStore = subStore(parentStore, 'about')
|
|
131
|
-
aboutStore.set({ header: 'About Us' })
|
|
132
|
-
// aboutStore state is { header: 'About Us' }
|
|
133
|
-
// parentStore state is { about: { header: 'About Us' }, events: { header: 'Events' } }
|
|
134
|
-
```
|
|
135
|
-
Note the use of a `subStore` function rather than `new SubStore`. `new SubStore` will work just
|
|
136
|
-
fine, but since typescript (at the time of writing) does not allow method overloads on the
|
|
137
|
-
constructor, there was no way to automatically derive types. Make a habit of using the `subStore`
|
|
138
|
-
function if you use typescript.
|
|
139
|
-
|
|
140
|
-
#### Subclassing SubStore
|
|
141
|
-
If you want to create a class and mutation methods for your SubStore, you'll want to create an
|
|
142
|
-
interface for your parent type that requires a minimum interface of the part you deal with. Then
|
|
143
|
-
you create a custom constructor with your accessor or setter/getter.
|
|
144
|
-
```typescript
|
|
145
|
-
interface AboutType {
|
|
146
|
-
header: string
|
|
147
|
-
}
|
|
148
|
-
interface HasAboutType {
|
|
149
|
-
about: AboutType
|
|
150
|
-
}
|
|
151
|
-
class AboutStore<ParentType extends HasAboutType> extends SubStore<AboutType, ParentType> {
|
|
152
|
-
constructor (parentStore: WritableSubject<ParentType>) {
|
|
153
|
-
super(parentStore, 'about')
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
updateHeader (newHeader: string) {
|
|
157
|
-
this.update(state => ({ ...state, header: newHeader }))
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
const parentStore = new Store({
|
|
161
|
-
about: { header: 'About' },
|
|
162
|
-
events: { header: 'Events' }
|
|
163
|
-
})
|
|
164
|
-
const aboutStore = new AboutStore(parentStore)
|
|
165
|
-
aboutStore.updateHeader('About Us')
|
|
166
|
-
```
|
|
167
|
-
Note the use of `WritableSubject` in the constructor. This is exported from our library, and is
|
|
168
|
-
a generic way of accepting any kind of store - it accepts anything with a `subscribe` and `update`
|
|
169
|
-
method. So you can write a SubStore that accepts default svelte stores as well as one of our stores.
|
|
170
|
-
|
|
171
|
-
### derivedStore
|
|
172
|
-
`derivedStore` is designed to allow you to compile data from one or more parent stores into another
|
|
173
|
-
read-only store. Each time any parent store changes, we'll run a function to derive a new state from
|
|
174
|
-
the parent state(s). This is extremely similar to svelte's `derived` store, but subscribers will only
|
|
175
|
-
be notified if the derived state has changed (uses fast-deep-equal instead of svelte's shallow equality).
|
|
176
|
-
```typescript
|
|
177
|
-
const num1Store = new Store(5)
|
|
178
|
-
const num2Store = new Store(7)
|
|
179
|
-
const sumStore = derivedStore([num1Store, num2Store], ([num1, num2]) => num1 + num2)
|
|
180
|
-
// sumStore state is 12
|
|
181
|
-
num1Store.set(3)
|
|
182
|
-
// sumStore state is 10
|
|
183
|
-
```
|
|
184
|
-
If you only use one parent store, it's possible to use a dot-prop string as the getter, basically a
|
|
185
|
-
read-only version of SubStore.
|
|
186
|
-
|
|
187
|
-
### convertStore
|
|
188
|
-
`convertStore` is provided to add deep equality checks to a svelte store. The state is duplicated into
|
|
189
|
-
one of our stores, but the duplicate is kept in sync with the parent svelte store and vice-versa. You can
|
|
190
|
-
feel free to `set` and `update` the converted store even if some of your code still uses the parent svelte
|
|
191
|
-
store.
|
|
192
|
-
```typescript
|
|
193
|
-
const svelteStore = writable({ putit: 'there' })
|
|
194
|
-
const deepEqualStore = convertStore(svelteStore)
|
|
195
|
-
svelteStore.set({ putit: 'here' })
|
|
196
|
-
// both stores have state { putit: 'here' }
|
|
197
|
-
deepEqualStore.set({ putit: 'there' })
|
|
198
|
-
// both stores are back to { putit: 'there' }
|
|
199
|
-
deepEqualStore.set({ putit: 'there' })
|
|
200
|
-
// no subscribers are notified, because deepEqualStore caught that nothing was updated
|
|
201
|
-
svelteStore.set({ putit: 'there' })
|
|
202
|
-
// svelteStore subscribers are notified, but deepEqualStore subscribers are not
|
|
203
|
-
```
|
package/esm/index.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from '../dist/index'
|
package/esm/package.json
DELETED