@txstate-mws/svelte-components 1.0.1 → 1.1.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/.eslintrc.cjs +37 -0
- package/README.md +33 -14
- package/docs/stores.md +1 -1
- package/package.json +24 -74
- package/playwright.config.js +112 -0
- package/src/app.html +14 -0
- package/src/global.d.ts +1 -0
- package/src/lib/actions/buttonify.ts +27 -0
- package/src/lib/actions/glue.ts +96 -0
- package/src/lib/actions/index.ts +7 -0
- package/src/lib/actions/offset.ts +43 -0
- package/src/lib/actions/portal.ts +13 -0
- package/src/lib/actions/resize.ts +72 -0
- package/src/lib/actions/sticky.ts +105 -0
- package/src/lib/actions/stickyfixed.ts +160 -0
- package/src/lib/components/Card.svelte +25 -0
- package/src/lib/components/CardLayout.svelte +188 -0
- package/{dist/ts → src/lib}/components/CollapsingTable.svelte +6 -5
- package/{dist/ts → src/lib}/components/ConditionalWrapper.svelte +0 -0
- package/{dist/ts → src/lib}/components/FocusLock.svelte +7 -6
- package/{dist/ts → src/lib}/components/Modal.svelte +5 -4
- package/src/lib/components/MultiSelect.svelte +174 -0
- package/{dist/ts → src/lib}/components/PopupMenu.svelte +22 -16
- package/{dist/ts → src/lib}/components/ScreenReaderOnly.svelte +2 -2
- package/src/lib/components/index.ts +9 -0
- package/src/lib/index.ts +4 -0
- package/src/lib/types/CardLayout.ts +14 -0
- package/src/lib/types/CollapsingTable.ts +8 -0
- package/src/lib/types/PopupMenu.ts +5 -0
- package/src/lib/types/index.ts +3 -0
- package/src/lib/util/bodyoffset.ts +77 -0
- package/src/lib/util/index.ts +3 -0
- package/src/lib/util/repositioned.ts +91 -0
- package/src/lib/util/util.ts +36 -0
- package/src/routes/__layout.svelte +125 -0
- package/src/routes/actions/index.svelte +1 -0
- package/src/routes/actions/offset.svelte +4 -0
- package/src/routes/actions/offsetdebounce.svelte +4 -0
- package/src/routes/actions/resize.svelte +4 -0
- package/src/routes/actions/resizedebounce.svelte +4 -0
- package/src/routes/actions/sticky.svelte +4 -0
- package/src/routes/cards/index.svelte +4 -0
- package/src/routes/cards/preserve.svelte +4 -0
- package/src/routes/collapsingtable/index.svelte +4 -0
- package/src/routes/collapsingtable/stickyheader.svelte +4 -0
- package/src/routes/index.svelte +2 -0
- package/src/routes/modal.svelte +4 -0
- package/src/routes/multiselect.svelte +4 -0
- package/src/routes/popupmenu/body.svelte +4 -0
- package/src/routes/popupmenu/complex.svelte +4 -0
- package/src/routes/popupmenu/empty.svelte +5 -0
- package/src/routes/popupmenu/index.svelte +4 -0
- package/src/routes/popupmenu/parent.svelte +4 -0
- package/src/routes/popupmenu/scrollable.svelte +27 -0
- package/src/routes/popupmenu/showselected.svelte +4 -0
- package/src/test/Cards.svelte +64 -0
- package/{dist/ts/tests/CollapsingTable → src/test}/CollapsingTableTest.svelte +2 -2
- package/{dist/ts/tests/Modal → src/test}/ModalTest.svelte +3 -3
- package/src/test/MultiSelectTest.svelte +26 -0
- package/{dist/ts/tests/Actions → src/test}/Offset.svelte +2 -4
- package/{dist/ts/tests/PopupMenu → src/test}/PopupMenuBody.svelte +1 -1
- package/{dist/ts/tests/PopupMenu → src/test}/PopupMenuButtonIsParent.svelte +2 -2
- package/{dist/ts/tests/PopupMenu → src/test}/PopupMenuComplex.svelte +2 -2
- package/{dist/ts/tests/PopupMenu → src/test}/PopupMenuSimple.svelte +2 -2
- package/{dist/ts/tests/Actions → src/test}/Resize.svelte +2 -4
- package/{dist/ts/tests/Actions → src/test}/Sticky.svelte +1 -1
- package/static/layout.css +263 -0
- package/svelte.config.js +15 -0
- package/tests/.eslintrc.cjs +19 -0
- package/tests/CardLayout.test.js +41 -0
- package/tests/CollapsingTable.test.js +37 -0
- package/tests/Modal.test.js +18 -0
- package/tests/MultiSelect.test.js +58 -0
- package/tests/PopupMenu.test.js +55 -0
- package/tests/common.js +4 -0
- package/tsconfig.json +31 -0
- package/LICENSE +0 -21
- package/dist/actions/buttonify.js +0 -31
- package/dist/actions/buttonify.js.map +0 -1
- package/dist/actions/glue.js +0 -87
- 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 +0 -93
- package/dist/actions/sticky.js.map +0 -1
- package/dist/actions/stickyfixed.js +0 -166
- package/dist/actions/stickyfixed.js.map +0 -1
- package/dist/components/CollapsingTable.svelte +0 -147
- package/dist/components/ConditionalWrapper.svelte +0 -38
- package/dist/components/FocusLock.svelte +0 -105
- package/dist/components/Modal.svelte +0 -52
- package/dist/components/PopupMenu.svelte +0 -282
- package/dist/components/ScreenReaderOnly.svelte +0 -25
- 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 +0 -76
- 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 +0 -92
- 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/buttonify.d.ts +0 -8
- package/dist/ts/actions/glue.d.ts +0 -16
- package/dist/ts/actions/index.d.ts +0 -7
- package/dist/ts/actions/offset.d.ts +0 -15
- package/dist/ts/actions/portal.d.ts +0 -4
- package/dist/ts/actions/resize.d.ts +0 -16
- package/dist/ts/actions/sticky.d.ts +0 -33
- package/dist/ts/actions/stickyfixed.d.ts +0 -25
- package/dist/ts/components/index.d.ts +0 -6
- package/dist/ts/index.d.ts +0 -4
- package/dist/ts/lib/activestore.d.ts +0 -60
- package/dist/ts/lib/bodyoffset.d.ts +0 -13
- 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/repositioned.d.ts +0 -13
- 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/lib/util.d.ts +0 -2
- package/dist/ts/tests/Actions/Actions.stories.d.ts +0 -1
- package/dist/ts/tests/CollapsingTable/CollapsingTable.stories.d.ts +0 -1
- package/dist/ts/tests/CollapsingTable/CollapsingTable.test.d.ts +0 -1
- 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/PopupMenu/PopupMenu.stories.d.ts +0 -1
- package/dist/ts/tests/PopupMenu/PopupMenu.test.d.ts +0 -1
- package/dist/ts/tests/stores/deepstore.test.d.ts +0 -1
- package/dist/ts/types/CollapsingTable.d.ts +0 -8
- package/dist/ts/types/PopupMenu.d.ts +0 -5
- 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/esm/index.js +0 -1
- package/esm/package.json +0 -3
package/.eslintrc.cjs
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
module.exports = {
|
|
2
|
+
root: true,
|
|
3
|
+
parser: '@typescript-eslint/parser',
|
|
4
|
+
extends: 'standard-with-typescript',
|
|
5
|
+
plugins: ['svelte3', '@typescript-eslint'],
|
|
6
|
+
ignorePatterns: ['*.cjs', 'package/**/*', 'svelte.config.js', 'playwright.config.js'],
|
|
7
|
+
overrides: [{ files: ['*.svelte'], processor: 'svelte3/svelte3' }],
|
|
8
|
+
settings: {
|
|
9
|
+
'svelte3/typescript': () => require('typescript')
|
|
10
|
+
},
|
|
11
|
+
rules: {
|
|
12
|
+
'import/first': 'off',
|
|
13
|
+
'no-multiple-empty-lines': 'off',
|
|
14
|
+
'no-undef-init': 'off',
|
|
15
|
+
'no-unused-vars': 'off',
|
|
16
|
+
'no-use-before-define': 'off',
|
|
17
|
+
'@typescript-eslint/explicit-function-return-type': 'off',
|
|
18
|
+
'@typescript-eslint/array-type': 'off',
|
|
19
|
+
'@typescript-eslint/no-non-null-assertion': 'off',
|
|
20
|
+
'@typescript-eslint/no-unused-vars': 'off', // typescript does this better
|
|
21
|
+
'@typescript-eslint/require-await': 'off',
|
|
22
|
+
'@typescript-eslint/return-await': ['error', 'always'],
|
|
23
|
+
'@typescript-eslint/strict-boolean-expressions': 'off',
|
|
24
|
+
'@typescript-eslint/prefer-readonly': ['off']
|
|
25
|
+
},
|
|
26
|
+
parserOptions: {
|
|
27
|
+
project: './tsconfig.json',
|
|
28
|
+
sourceType: 'module',
|
|
29
|
+
extraFileExtensions: ['.svelte'],
|
|
30
|
+
ecmaVersion: 2020
|
|
31
|
+
},
|
|
32
|
+
env: {
|
|
33
|
+
browser: true,
|
|
34
|
+
es2017: true,
|
|
35
|
+
node: true
|
|
36
|
+
}
|
|
37
|
+
};
|
package/README.md
CHANGED
|
@@ -1,17 +1,36 @@
|
|
|
1
1
|
# svelte-components
|
|
2
2
|
A set of generically useful components for svelte.
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
[CollapsingTable](/docs/CollapsingTable.md)
|
|
6
|
-
[ConditionalWrapper](/docs/ConditionalWrapper.md)
|
|
7
|
-
[FocusLock](/docs/Modal.md#FocusLock)
|
|
8
|
-
[Modal](/docs/Modal.md#Modal)
|
|
9
|
-
[PopupMenu](/docs/PopupMenu.md)
|
|
10
|
-
[ScreenReaderOnly](/docs/ScreenReaderOnly.md)
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
[use:buttonify](/docs/actions.md#use:buttonify)
|
|
14
|
-
[use:glue](/docs/actions.md#use:glue)
|
|
15
|
-
[use:offset](/docs/actions.md#use:offset)
|
|
16
|
-
[use:portal](/docs/actions.md#use:portal)
|
|
17
|
-
[use:resize](/docs/actions.md#use:resize)
|
|
4
|
+
## Components
|
|
5
|
+
- [CollapsingTable](/docs/CollapsingTable.md)
|
|
6
|
+
- [ConditionalWrapper](/docs/ConditionalWrapper.md)
|
|
7
|
+
- [FocusLock](/docs/Modal.md#FocusLock)
|
|
8
|
+
- [Modal](/docs/Modal.md#Modal)
|
|
9
|
+
- [PopupMenu](/docs/PopupMenu.md)
|
|
10
|
+
- [ScreenReaderOnly](/docs/ScreenReaderOnly.md)
|
|
11
|
+
|
|
12
|
+
## Actions
|
|
13
|
+
- [use:buttonify](/docs/actions.md#use:buttonify)
|
|
14
|
+
- [use:glue](/docs/actions.md#use:glue)
|
|
15
|
+
- [use:offset](/docs/actions.md#use:offset)
|
|
16
|
+
- [use:portal](/docs/actions.md#use:portal)
|
|
17
|
+
- [use:resize](/docs/actions.md#use:resize)
|
|
18
|
+
|
|
19
|
+
## Developing
|
|
20
|
+
|
|
21
|
+
Installed dependencies with `npm install`, then start the development server:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
npm run dev
|
|
25
|
+
|
|
26
|
+
# or start the server and open the app in a new browser tab
|
|
27
|
+
npm run dev -- --open
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Publishing to npm
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
npm run package
|
|
34
|
+
cd package
|
|
35
|
+
npm publish
|
|
36
|
+
```
|
package/docs/stores.md
CHANGED
|
@@ -172,7 +172,7 @@ method. So you can write a SubStore that accepts default svelte stores as well a
|
|
|
172
172
|
`derivedStore` is designed to allow you to compile data from one or more parent stores into another
|
|
173
173
|
read-only store. Each time any parent store changes, we'll run a function to derive a new state from
|
|
174
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
|
|
175
|
+
be notified if the derived state has changed (uses a deep-equal instead of svelte's shallow equality).
|
|
176
176
|
```typescript
|
|
177
177
|
const num1Store = new Store(5)
|
|
178
178
|
const num2Store = new Store(7)
|
package/package.json
CHANGED
|
@@ -1,85 +1,35 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@txstate-mws/svelte-components",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "Svelte components that are generically useful.",
|
|
5
|
-
"main": "dist/index.js",
|
|
6
|
-
"module": "esm/index.js",
|
|
7
|
-
"exports": {
|
|
8
|
-
".": {
|
|
9
|
-
"require": "./dist/index.js",
|
|
10
|
-
"import": "./esm/index.js"
|
|
11
|
-
},
|
|
12
|
-
"./package.json": "./package.json"
|
|
13
|
-
},
|
|
14
|
-
"types": "dist/ts/index.d.ts",
|
|
15
5
|
"scripts": {
|
|
16
|
-
"
|
|
17
|
-
"
|
|
18
|
-
"
|
|
19
|
-
"
|
|
20
|
-
"
|
|
21
|
-
"
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
"type": "git",
|
|
25
|
-
"url": "git@github.com:txstate-etc/svelte-components.git"
|
|
6
|
+
"dev": "svelte-kit dev",
|
|
7
|
+
"build": "svelte-kit build",
|
|
8
|
+
"package": "svelte-kit package",
|
|
9
|
+
"preview": "svelte-kit preview",
|
|
10
|
+
"check": "svelte-check --tsconfig ./tsconfig.json",
|
|
11
|
+
"check:watch": "svelte-check --tsconfig ./tsconfig.json --watch",
|
|
12
|
+
"lint": "eslint --ignore-path .gitignore .",
|
|
13
|
+
"test": "playwright test tests"
|
|
26
14
|
},
|
|
27
|
-
"author": "Nick Wing",
|
|
28
|
-
"license": "MIT",
|
|
29
15
|
"dependencies": {
|
|
30
|
-
"
|
|
31
|
-
"
|
|
32
|
-
"
|
|
33
|
-
"txstate-utils": "^1.4.0"
|
|
16
|
+
"@txstate-mws/svelte-store": "^1.0.3",
|
|
17
|
+
"tabbable": "^5.2.1",
|
|
18
|
+
"txstate-utils": "^1.6.0"
|
|
34
19
|
},
|
|
35
20
|
"devDependencies": {
|
|
36
|
-
"@
|
|
37
|
-
"@
|
|
38
|
-
"@
|
|
39
|
-
"@
|
|
40
|
-
"@tsconfig/svelte": "^3.0.0",
|
|
41
|
-
"@types/jest": "^27.0.2",
|
|
42
|
-
"@types/node": "^15.3.1",
|
|
43
|
-
"babel-jest": "^27.3.1",
|
|
21
|
+
"@playwright/test": "^1.18.1",
|
|
22
|
+
"@sveltejs/adapter-auto": "next",
|
|
23
|
+
"@sveltejs/kit": "next",
|
|
24
|
+
"@types/tabbable": "^3.1.2",
|
|
44
25
|
"eslint-config-standard-with-typescript": "^21.0.1",
|
|
45
|
-
"eslint-plugin-svelte3": "^3.
|
|
46
|
-
"
|
|
47
|
-
"
|
|
48
|
-
"
|
|
49
|
-
"
|
|
50
|
-
"
|
|
51
|
-
"
|
|
52
|
-
"svelte-preprocess": "^4.6.5",
|
|
53
|
-
"ts-jest": "^27.0.7",
|
|
54
|
-
"tslib": "^2.1.0",
|
|
55
|
-
"typescript": "^4.1.3"
|
|
56
|
-
},
|
|
57
|
-
"jest": {
|
|
58
|
-
"testEnvironment": "jsdom",
|
|
59
|
-
"transform": {
|
|
60
|
-
"^.+\\.js$": "babel-jest",
|
|
61
|
-
"^.+\\.ts$": "ts-jest",
|
|
62
|
-
"^.+\\.svelte$": [
|
|
63
|
-
"svelte-jester",
|
|
64
|
-
{
|
|
65
|
-
"preprocess": true
|
|
66
|
-
}
|
|
67
|
-
]
|
|
68
|
-
},
|
|
69
|
-
"transformIgnorePatterns": [],
|
|
70
|
-
"moduleFileExtensions": [
|
|
71
|
-
"js",
|
|
72
|
-
"ts",
|
|
73
|
-
"svelte"
|
|
74
|
-
],
|
|
75
|
-
"setupFilesAfterEnv": [
|
|
76
|
-
"@testing-library/jest-dom"
|
|
77
|
-
]
|
|
26
|
+
"eslint-plugin-svelte3": "^3.2.1",
|
|
27
|
+
"svelte": "^3.44.0",
|
|
28
|
+
"svelte-check": "^2.2.6",
|
|
29
|
+
"svelte-preprocess": "^4.9.4",
|
|
30
|
+
"svelte2tsx": "^0.5.2",
|
|
31
|
+
"tslib": "^2.3.1",
|
|
32
|
+
"typescript": "^4.4.3"
|
|
78
33
|
},
|
|
79
|
-
"
|
|
80
|
-
"files": [
|
|
81
|
-
"dist",
|
|
82
|
-
"esm",
|
|
83
|
-
"docs"
|
|
84
|
-
]
|
|
34
|
+
"type": "module"
|
|
85
35
|
}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { devices } from '@playwright/test';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* See https://playwright.dev/docs/test-configuration.
|
|
5
|
+
*/
|
|
6
|
+
export const config = {
|
|
7
|
+
|
|
8
|
+
testDir: './tests',
|
|
9
|
+
|
|
10
|
+
/* Maximum time one test can run for. */
|
|
11
|
+
timeout: 30 * 1000,
|
|
12
|
+
|
|
13
|
+
expect: {
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Maximum time expect() should wait for the condition to be met.
|
|
17
|
+
* For example in `await expect(locator).toHaveText();`
|
|
18
|
+
*/
|
|
19
|
+
timeout: 5000
|
|
20
|
+
},
|
|
21
|
+
|
|
22
|
+
/* Fail the build on CI if you accidentally left test.only in the source code. */
|
|
23
|
+
forbidOnly: !!process.env.CI,
|
|
24
|
+
|
|
25
|
+
/* Retry on CI only */
|
|
26
|
+
retries: process.env.CI ? 2 : 0,
|
|
27
|
+
|
|
28
|
+
/* Opt out of parallel tests on CI. */
|
|
29
|
+
workers: process.env.CI ? 1 : undefined,
|
|
30
|
+
|
|
31
|
+
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
|
|
32
|
+
reporter: 'line',
|
|
33
|
+
|
|
34
|
+
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
|
|
35
|
+
use: {
|
|
36
|
+
|
|
37
|
+
/* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */
|
|
38
|
+
actionTimeout: 0,
|
|
39
|
+
|
|
40
|
+
/* Base URL to use in actions like `await page.goto('/')`. */
|
|
41
|
+
// baseURL: 'http://localhost:3000',
|
|
42
|
+
|
|
43
|
+
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
|
|
44
|
+
trace: 'on-first-retry',
|
|
45
|
+
},
|
|
46
|
+
|
|
47
|
+
/* Configure projects for major browsers */
|
|
48
|
+
projects: [
|
|
49
|
+
{
|
|
50
|
+
name: 'chromium',
|
|
51
|
+
|
|
52
|
+
/* Project-specific settings. */
|
|
53
|
+
use: {
|
|
54
|
+
...devices['Desktop Chrome'],
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
|
|
58
|
+
{
|
|
59
|
+
name: 'firefox',
|
|
60
|
+
use: {
|
|
61
|
+
...devices['Desktop Firefox'],
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
|
|
65
|
+
{
|
|
66
|
+
name: 'webkit',
|
|
67
|
+
use: {
|
|
68
|
+
...devices['Desktop Safari'],
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
|
|
72
|
+
/* Test against mobile viewports. */
|
|
73
|
+
// {
|
|
74
|
+
// name: 'Mobile Chrome',
|
|
75
|
+
// use: {
|
|
76
|
+
// ...devices['Pixel 5'],
|
|
77
|
+
// },
|
|
78
|
+
// },
|
|
79
|
+
// {
|
|
80
|
+
// name: 'Mobile Safari',
|
|
81
|
+
// use: {
|
|
82
|
+
// ...devices['iPhone 12'],
|
|
83
|
+
// },
|
|
84
|
+
// },
|
|
85
|
+
|
|
86
|
+
/* Test against branded browsers. */
|
|
87
|
+
// {
|
|
88
|
+
// name: 'Microsoft Edge',
|
|
89
|
+
// use: {
|
|
90
|
+
// channel: 'msedge',
|
|
91
|
+
// },
|
|
92
|
+
// },
|
|
93
|
+
// {
|
|
94
|
+
// name: 'Google Chrome',
|
|
95
|
+
// use: {
|
|
96
|
+
// channel: 'chrome',
|
|
97
|
+
// },
|
|
98
|
+
// },
|
|
99
|
+
],
|
|
100
|
+
|
|
101
|
+
/* Folder for test artifacts such as screenshots, videos, traces, etc. */
|
|
102
|
+
// outputDir: 'test-results/',
|
|
103
|
+
|
|
104
|
+
/* Run your local dev server before starting the tests */
|
|
105
|
+
webServer: {
|
|
106
|
+
command: 'npm run build && npm run preview',
|
|
107
|
+
port: 3000,
|
|
108
|
+
timeout: 120 * 1000,
|
|
109
|
+
reuseExistingServer: !process.env.CI
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
export default config;
|
package/src/app.html
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8" />
|
|
5
|
+
<meta name="description" content="" />
|
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
7
|
+
<link rel="stylesheet" href="https://unpkg.com/purecss@2.0.6/build/pure-min.css" integrity="sha384-Uu6IeWbM+gzNVXJcM9XV3SohHtmWE+3VGi496jvgX1jyvDTXfdK+rfZc8C1Aehk5" crossorigin="anonymous">
|
|
8
|
+
<link rel="stylesheet" href="/layout.css" />
|
|
9
|
+
%svelte.head%
|
|
10
|
+
</head>
|
|
11
|
+
<body>
|
|
12
|
+
<div id="svelte">%svelte.body%</div>
|
|
13
|
+
</body>
|
|
14
|
+
</html>
|
package/src/global.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
/// <reference types="@sveltejs/kit" />
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Turns any HTML element into an accessible button that responds to keyboard events and has
|
|
3
|
+
* role="button" and the tabindex attribute set. You are still responsible for making sure it has
|
|
4
|
+
* readable content or a good label.
|
|
5
|
+
*/
|
|
6
|
+
export function buttonify (node: HTMLElement) {
|
|
7
|
+
function keydown (e: KeyboardEvent) {
|
|
8
|
+
if (e.key === 'Enter') {
|
|
9
|
+
if (!e.shiftKey && !e.metaKey && !e.ctrlKey && !e.altKey) {
|
|
10
|
+
e.preventDefault()
|
|
11
|
+
e.stopPropagation()
|
|
12
|
+
node.dispatchEvent(new CustomEvent('click'))
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
node.addEventListener('keydown', keydown)
|
|
18
|
+
if (node.tabIndex < 0) node.tabIndex = 0
|
|
19
|
+
node.setAttribute('role', 'button')
|
|
20
|
+
node.style.cursor = 'pointer'
|
|
21
|
+
|
|
22
|
+
return {
|
|
23
|
+
destroy () {
|
|
24
|
+
node.removeEventListener('keydown', keydown)
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import type { SettableSubject } from '@txstate-mws/svelte-store'
|
|
2
|
+
import { sharedOffsetParent, targetOffset, watchForPositionChangeInContainer } from '../util/index.js'
|
|
3
|
+
import type { ElementOffsets } from '../util/index.js'
|
|
4
|
+
export type GlueAlignOpts = 'auto'|'bottomleft'|'bottomright'|'topleft'|'topright'
|
|
5
|
+
|
|
6
|
+
export interface GlueArgs<T extends GlueAlignStore = GlueAlignStore> {
|
|
7
|
+
target: HTMLElement
|
|
8
|
+
align?: GlueAlignOpts
|
|
9
|
+
cover?: boolean
|
|
10
|
+
store?: SettableSubject<T>
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface GlueAlignStore {
|
|
14
|
+
valign: 'bottom'|'top'
|
|
15
|
+
halign: 'left'|'right'
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
let setBodyRelative = false
|
|
19
|
+
export function glue (el: HTMLElement, { target, align = 'auto', cover = false, store }: GlueArgs) {
|
|
20
|
+
if (!setBodyRelative) {
|
|
21
|
+
setBodyRelative = true
|
|
22
|
+
document.body.style.position = 'relative'
|
|
23
|
+
}
|
|
24
|
+
let halign: GlueAlignStore['halign']
|
|
25
|
+
let valign: GlueAlignStore['valign']
|
|
26
|
+
let sharedOffset = sharedOffsetParent(el, target)
|
|
27
|
+
|
|
28
|
+
function reposition (offset: Required<ElementOffsets>) {
|
|
29
|
+
if (!target || !sharedOffset || !(el.offsetParent instanceof HTMLElement)) return
|
|
30
|
+
let autoalign = align
|
|
31
|
+
const parentoffset = el.offsetParent === sharedOffset && target !== sharedOffset ? { top: 0, left: 0, bottom: 0, right: 0 } : targetOffset(el.offsetParent, sharedOffset)
|
|
32
|
+
if (align === 'auto') {
|
|
33
|
+
const rect = target.getBoundingClientRect()
|
|
34
|
+
const leftright = window.innerWidth - rect.right > rect.left ? 'left' : 'right'
|
|
35
|
+
const topbottom = window.innerHeight - rect.bottom > rect.top ? 'bottom' : 'top'
|
|
36
|
+
autoalign = topbottom + leftright as 'auto'
|
|
37
|
+
}
|
|
38
|
+
const targetHeight = target.offsetHeight
|
|
39
|
+
if (autoalign === 'bottomleft') {
|
|
40
|
+
requestAnimationFrame(() => {
|
|
41
|
+
el.style.top = `${offset.top + (cover ? 0 : targetHeight) - parentoffset.top}px`
|
|
42
|
+
el.style.left = `${offset.left - parentoffset.left}px`
|
|
43
|
+
el.style.bottom = ''
|
|
44
|
+
el.style.right = ''
|
|
45
|
+
})
|
|
46
|
+
valign = 'bottom'
|
|
47
|
+
halign = 'left'
|
|
48
|
+
} else if (autoalign === 'bottomright') {
|
|
49
|
+
requestAnimationFrame(() => {
|
|
50
|
+
el.style.top = `${offset.top + (cover ? 0 : targetHeight) - parentoffset.top}px`
|
|
51
|
+
el.style.left = ''
|
|
52
|
+
el.style.bottom = ''
|
|
53
|
+
el.style.right = `${offset.right - parentoffset.right}px`
|
|
54
|
+
})
|
|
55
|
+
valign = 'bottom'
|
|
56
|
+
halign = 'right'
|
|
57
|
+
} else if (autoalign === 'topleft') {
|
|
58
|
+
requestAnimationFrame(() => {
|
|
59
|
+
el.style.top = ''
|
|
60
|
+
el.style.left = `${offset.left - parentoffset.left}px`
|
|
61
|
+
el.style.bottom = `${offset.bottom + (cover ? 0 : targetHeight) - parentoffset.bottom}px`
|
|
62
|
+
el.style.right = ''
|
|
63
|
+
})
|
|
64
|
+
valign = 'top'
|
|
65
|
+
halign = 'left'
|
|
66
|
+
} else if (autoalign === 'topright') {
|
|
67
|
+
requestAnimationFrame(() => {
|
|
68
|
+
el.style.top = ''
|
|
69
|
+
el.style.left = ''
|
|
70
|
+
el.style.bottom = `${offset.bottom + (cover ? 0 : targetHeight) - parentoffset.bottom}px`
|
|
71
|
+
el.style.right = `${offset.right - parentoffset.right}px`
|
|
72
|
+
})
|
|
73
|
+
valign = 'top'
|
|
74
|
+
halign = 'right'
|
|
75
|
+
}
|
|
76
|
+
store?.update(v => ({ ...v, valign, halign }))
|
|
77
|
+
}
|
|
78
|
+
const { destroy, update } = watchForPositionChangeInContainer(target, sharedOffset, reposition)
|
|
79
|
+
|
|
80
|
+
return {
|
|
81
|
+
update ({ target: utarget, align: ualign = 'auto', cover: ucover = false, store: ustore }: GlueArgs) {
|
|
82
|
+
align = ualign
|
|
83
|
+
cover = ucover
|
|
84
|
+
if (ustore && ustore !== store) {
|
|
85
|
+
ustore.update(v => ({ ...v, valign, halign }))
|
|
86
|
+
store = ustore
|
|
87
|
+
}
|
|
88
|
+
if (target !== utarget) {
|
|
89
|
+
sharedOffset = sharedOffsetParent(el, utarget)
|
|
90
|
+
target = utarget
|
|
91
|
+
update(target, sharedOffset, reposition)
|
|
92
|
+
}
|
|
93
|
+
},
|
|
94
|
+
destroy
|
|
95
|
+
}
|
|
96
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { Store } from '@txstate-mws/svelte-store'
|
|
2
|
+
import type { WritableSubject } from '@txstate-mws/svelte-store'
|
|
3
|
+
import { debounced, watchForPositionChange } from '../util/index.js'
|
|
4
|
+
import type { ElementOffsets } from '../util/index.js'
|
|
5
|
+
|
|
6
|
+
interface OffsetConfig<T extends ElementOffsets = ElementOffsets> {
|
|
7
|
+
debounce?: boolean|number
|
|
8
|
+
store?: WritableSubject<T>
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export class OffsetStore extends Store<ElementOffsets> {
|
|
12
|
+
constructor (initialState?: ElementOffsets) {
|
|
13
|
+
super(initialState ?? { top: 0, right: 0, bottom: 0, left: 0 })
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function offset (el: HTMLElement, config?: OffsetConfig) {
|
|
18
|
+
if (config?.debounce === true) config.debounce = 100
|
|
19
|
+
let lastOffset: ElementOffsets = {}
|
|
20
|
+
function lookforoffsetchange (current: ElementOffsets) {
|
|
21
|
+
lastOffset = current
|
|
22
|
+
if (config?.store) config.store.update(v => ({ ...v, ...current }))
|
|
23
|
+
el.dispatchEvent(new CustomEvent('offset', { detail: current }))
|
|
24
|
+
}
|
|
25
|
+
let resolvedchange = config?.debounce ? debounced(lookforoffsetchange, config.debounce) : lookforoffsetchange
|
|
26
|
+
|
|
27
|
+
const { destroy, update } = watchForPositionChange(el, resolvedchange)
|
|
28
|
+
|
|
29
|
+
return {
|
|
30
|
+
update (newConfig?: OffsetConfig) {
|
|
31
|
+
if (newConfig?.debounce === true) newConfig.debounce = 100
|
|
32
|
+
if (newConfig?.store !== config?.store) {
|
|
33
|
+
newConfig?.store?.update(v => ({ ...v, ...lastOffset }))
|
|
34
|
+
}
|
|
35
|
+
if (newConfig?.debounce !== config?.debounce) {
|
|
36
|
+
resolvedchange = newConfig?.debounce ? debounced(lookforoffsetchange, newConfig.debounce as any) : lookforoffsetchange
|
|
37
|
+
update(el, resolvedchange)
|
|
38
|
+
}
|
|
39
|
+
config = newConfig
|
|
40
|
+
},
|
|
41
|
+
destroy
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export function portal (el: HTMLElement, target: HTMLElement|null = document.body) {
|
|
2
|
+
function update (target: HTMLElement|null = document.body) {
|
|
3
|
+
target?.appendChild(el)
|
|
4
|
+
}
|
|
5
|
+
function destroy () {
|
|
6
|
+
el.parentElement?.removeChild(el)
|
|
7
|
+
}
|
|
8
|
+
update(target)
|
|
9
|
+
return {
|
|
10
|
+
update,
|
|
11
|
+
destroy
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { equal } from 'txstate-utils'
|
|
2
|
+
import { Store } from '@txstate-mws/svelte-store'
|
|
3
|
+
import type { SettableSubject } from '@txstate-mws/svelte-store'
|
|
4
|
+
import { debounced } from '../util/index.js'
|
|
5
|
+
|
|
6
|
+
export interface ElementSize {
|
|
7
|
+
clientWidth?: number
|
|
8
|
+
clientHeight?: number
|
|
9
|
+
offsetWidth?: number
|
|
10
|
+
offsetHeight?: number
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
interface ResizeConfig {
|
|
14
|
+
debounce?: boolean|number
|
|
15
|
+
store?: SettableSubject<ElementSize>
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export class ResizeStore extends Store<ElementSize> {
|
|
19
|
+
constructor (initialState?: ElementSize) {
|
|
20
|
+
super(initialState ?? typeof window === 'undefined'
|
|
21
|
+
? {
|
|
22
|
+
clientWidth: 1024,
|
|
23
|
+
clientHeight: 1024,
|
|
24
|
+
offsetWidth: 1024,
|
|
25
|
+
offsetHeight: 1024
|
|
26
|
+
}
|
|
27
|
+
: {
|
|
28
|
+
clientWidth: window.innerWidth,
|
|
29
|
+
clientHeight: window.innerHeight,
|
|
30
|
+
offsetWidth: window.innerWidth,
|
|
31
|
+
offsetHeight: window.innerHeight
|
|
32
|
+
}
|
|
33
|
+
)
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function resize (el: HTMLElement, config?: ResizeConfig) {
|
|
38
|
+
if (config?.debounce === true) config.debounce = 100
|
|
39
|
+
let lastSize: ElementSize = {}
|
|
40
|
+
function watch () {
|
|
41
|
+
const current = { clientWidth: el.clientWidth, clientHeight: el.clientHeight, offsetWidth: el.offsetWidth, offsetHeight: el.offsetHeight }
|
|
42
|
+
if (!equal(lastSize, current)) {
|
|
43
|
+
lastSize = current
|
|
44
|
+
if (config?.store) config.store.set(current)
|
|
45
|
+
el.dispatchEvent(new CustomEvent('resize', { detail: current }))
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (typeof ResizeObserver === 'undefined') return watch() // support SSR
|
|
50
|
+
|
|
51
|
+
let observer = new ResizeObserver(config?.debounce ? debounced(watch, config.debounce) : watch)
|
|
52
|
+
observer.observe(el)
|
|
53
|
+
watch()
|
|
54
|
+
|
|
55
|
+
return {
|
|
56
|
+
update (newConfig?: ResizeConfig) {
|
|
57
|
+
if (newConfig?.debounce === true) newConfig.debounce = 100
|
|
58
|
+
if (newConfig?.store !== config?.store) {
|
|
59
|
+
newConfig?.store?.set(lastSize)
|
|
60
|
+
}
|
|
61
|
+
if (!!newConfig?.debounce !== !!config?.debounce) {
|
|
62
|
+
observer.disconnect()
|
|
63
|
+
observer = new ResizeObserver(newConfig?.debounce ? debounced(watch, newConfig.debounce) : watch)
|
|
64
|
+
observer.observe(el)
|
|
65
|
+
}
|
|
66
|
+
config = newConfig
|
|
67
|
+
},
|
|
68
|
+
destroy () {
|
|
69
|
+
observer.disconnect()
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|