├── .editorconfig
├── .eslintrc.cjs
├── .gitignore
├── .husky
└── pre-commit
├── .npmrc
├── .prettierrc
├── LICENSE
├── README.md
├── mdsvex.config.js
├── package-lock.json
├── package.json
├── src
├── global.d.ts
├── lib
│ ├── Spectre.svelte
│ ├── components
│ │ ├── Accordion
│ │ │ ├── Accordion.svelte
│ │ │ ├── Accordioner.svelte
│ │ │ └── index.ts
│ │ ├── Autocomplete
│ │ │ ├── Autocomplete.svelte
│ │ │ ├── index.ts
│ │ │ └── utils.ts
│ │ ├── Avatar
│ │ │ ├── Avatar.svelte
│ │ │ └── index.ts
│ │ ├── Badge
│ │ │ ├── Badge.svelte
│ │ │ ├── action.ts
│ │ │ └── index.ts
│ │ ├── Bars
│ │ │ ├── Bars.svelte
│ │ │ └── index.ts
│ │ ├── Breadcrumbs
│ │ │ ├── Breadcrumbs.svelte
│ │ │ └── index.ts
│ │ ├── Button
│ │ │ ├── Button.svelte
│ │ │ ├── Group.svelte
│ │ │ ├── IconButton.svelte
│ │ │ └── index.ts
│ │ ├── Checkbox
│ │ │ ├── Checkbox.svelte
│ │ │ └── index.ts
│ │ ├── Chip
│ │ │ ├── Chip.svelte
│ │ │ └── index.ts
│ │ ├── Divider
│ │ │ ├── Divider.svelte
│ │ │ └── index.ts
│ │ ├── Icon
│ │ │ ├── Icon.svelte
│ │ │ └── index.ts
│ │ ├── Input
│ │ │ ├── Group.svelte
│ │ │ ├── Input.svelte
│ │ │ └── index.ts
│ │ ├── Menu
│ │ │ ├── Menu.svelte
│ │ │ └── index.ts
│ │ ├── Meter
│ │ │ ├── Meter.svelte
│ │ │ └── index.ts
│ │ ├── Pagination
│ │ │ ├── Pagination.svelte
│ │ │ └── index.ts
│ │ ├── PeriodicTable
│ │ │ ├── PeriodicTable.svelte
│ │ │ ├── chemical_content.json
│ │ │ ├── index.ts
│ │ │ └── table_data.json
│ │ ├── Progress
│ │ │ ├── Progress.svelte
│ │ │ └── index.ts
│ │ ├── Radio
│ │ │ ├── Radio.svelte
│ │ │ └── index.ts
│ │ ├── Range
│ │ │ ├── Range.svelte
│ │ │ └── index.ts
│ │ ├── Select
│ │ │ ├── Select.svelte
│ │ │ └── index.ts
│ │ ├── Steps
│ │ │ ├── Steps.svelte
│ │ │ └── index.ts
│ │ ├── Switch
│ │ │ ├── Switch.svelte
│ │ │ └── index.ts
│ │ ├── Tabs
│ │ │ ├── Tabs.svelte
│ │ │ └── index.ts
│ │ ├── Toast
│ │ │ ├── Toast.svelte
│ │ │ ├── Toaster.svelte
│ │ │ ├── index.ts
│ │ │ ├── positions.ts
│ │ │ ├── timer.ts
│ │ │ └── toast.ts
│ │ ├── Transition
│ │ │ ├── Transition.svelte
│ │ │ └── index.ts
│ │ └── index.ts
│ ├── dark.scss
│ ├── helpers
│ │ ├── actions.ts
│ │ ├── str_to_rgb.ts
│ │ └── uuid.ts
│ ├── index.ts
│ ├── layouts
│ │ ├── Card
│ │ │ ├── Card.svelte
│ │ │ └── index.ts
│ │ ├── Code
│ │ │ ├── Code.svelte
│ │ │ └── index.ts
│ │ ├── Container
│ │ │ ├── Container.svelte
│ │ │ └── index.ts
│ │ ├── Dropdown
│ │ │ ├── Dropdown.svelte
│ │ │ └── index.ts
│ │ ├── Empty
│ │ │ ├── Empty.svelte
│ │ │ └── index.ts
│ │ ├── Figure
│ │ │ ├── Figure.svelte
│ │ │ └── index.ts
│ │ ├── Form
│ │ │ ├── Form.svelte
│ │ │ ├── Group.svelte
│ │ │ └── index.ts
│ │ ├── Grid
│ │ │ ├── Col.svelte
│ │ │ ├── Grid.svelte
│ │ │ └── index.ts
│ │ ├── Hero
│ │ │ ├── Hero.svelte
│ │ │ └── index.ts
│ │ ├── Modal
│ │ │ ├── Modal.svelte
│ │ │ └── index.ts
│ │ ├── Navbar
│ │ │ ├── Navbar.svelte
│ │ │ └── index.ts
│ │ ├── Panel
│ │ │ ├── Panel.svelte
│ │ │ └── index.ts
│ │ ├── Popover
│ │ │ ├── Popover.svelte
│ │ │ └── index.ts
│ │ ├── Sidebar
│ │ │ ├── Sidebar.svelte
│ │ │ └── index.ts
│ │ ├── Tile
│ │ │ ├── Tile.svelte
│ │ │ └── index.ts
│ │ ├── Toggle
│ │ │ ├── Toggle.svelte
│ │ │ └── index.ts
│ │ └── index.ts
│ ├── spectre.scss
│ └── types
│ │ ├── asset.d.ts
│ │ ├── bg.d.ts
│ │ ├── const.ts
│ │ ├── display.d.ts
│ │ ├── icons.d.ts
│ │ ├── position.d.ts
│ │ ├── shape.d.ts
│ │ ├── size.d.ts
│ │ └── text.d.ts
└── www
│ ├── +layout.server.ts
│ ├── +layout.svelte
│ ├── +page.svelte
│ ├── app.html
│ ├── app.scss
│ ├── assets
│ ├── .nojekyll
│ ├── favicon.svg
│ ├── fonts
│ │ └── Exo2_64_Latin-ext.scss
│ ├── github.svg
│ ├── img
│ │ ├── 04696e1a-eb5d-43b9-bb1d-d2ee117f4430.webp
│ │ ├── 1b9a004a-db27-45e4-b762-0fa21bc97277.webp
│ │ ├── 4603a846-4daf-4018-aa74-e3ab567a69fc.webp
│ │ ├── avatar-1.png
│ │ ├── avatar-2.png
│ │ ├── avatar-3.png
│ │ ├── avatar-4.png
│ │ ├── avatar-5.png
│ │ ├── b64f151d-e194-497a-9b70-e15ffdd8730d.webp
│ │ └── c2179403-954f-4f5d-82a4-3dfdeaba9597.webp
│ └── metis.svg
│ ├── docs
│ ├── +layout.svelte
│ ├── +page.svelte
│ ├── 01-getting_started
│ │ ├── 01-installation
│ │ │ └── +page.md
│ │ ├── 02-customize
│ │ │ └── +page.md
│ │ ├── browser-support
│ │ │ └── +page.md
│ │ └── changelog
│ │ │ └── +page.md
│ ├── code.scss
│ ├── components
│ │ ├── accordion
│ │ │ └── +page.md
│ │ ├── autocomplete
│ │ │ └── +page.md
│ │ ├── avatar
│ │ │ └── +page.md
│ │ ├── badge
│ │ │ └── +page.md
│ │ ├── bars
│ │ │ └── +page.md
│ │ ├── breadcrumbs
│ │ │ └── +page.md
│ │ ├── button
│ │ │ └── +page.md
│ │ ├── checkbox
│ │ │ └── +page.md
│ │ ├── chip
│ │ │ └── +page.md
│ │ ├── divider
│ │ │ └── +page.md
│ │ ├── icon
│ │ │ └── +page.md
│ │ ├── input
│ │ │ └── +page.md
│ │ ├── menu
│ │ │ └── +page.md
│ │ ├── meter
│ │ │ └── +page.md
│ │ ├── pagination
│ │ │ └── +page.md
│ │ ├── periodictable
│ │ │ └── +page.md
│ │ ├── progress
│ │ │ └── +page.md
│ │ ├── radio
│ │ │ └── +page.md
│ │ ├── range
│ │ │ └── +page.md
│ │ ├── select
│ │ │ └── +page.md
│ │ ├── steps
│ │ │ └── +page.md
│ │ ├── switch
│ │ │ └── +page.md
│ │ ├── tabs
│ │ │ └── +page.md
│ │ ├── toast
│ │ │ └── +page.md
│ │ └── transition
│ │ │ └── +page.md
│ ├── knobs.svelte
│ └── layouts
│ │ ├── card
│ │ └── +page.md
│ │ ├── code
│ │ └── +page.md
│ │ ├── container
│ │ └── +page.md
│ │ ├── dropdown
│ │ └── +page.md
│ │ ├── empty
│ │ └── +page.md
│ │ ├── figure
│ │ └── +page.md
│ │ ├── form
│ │ └── +page.md
│ │ ├── grid
│ │ └── +page.md
│ │ ├── hero
│ │ └── +page.md
│ │ ├── modal
│ │ └── +page.md
│ │ ├── navbar
│ │ └── +page.md
│ │ ├── panel
│ │ └── +page.md
│ │ ├── popover
│ │ └── +page.md
│ │ ├── sidebar
│ │ └── +page.md
│ │ ├── tile
│ │ └── +page.md
│ │ └── toggle
│ │ └── +page.md
│ ├── media.ts
│ └── types.ts
├── svelte.config.js
├── tests
├── components
│ ├── Accordion
│ │ └── Accordion.spec.ts
│ ├── Avatar
│ │ └── Avatar.spec.ts
│ ├── Badge
│ │ └── Badge.spec.ts
│ ├── Breadcrumbs
│ │ └── Breadcrumbs.spec.ts
│ ├── Button
│ │ ├── Button.spec.ts
│ │ ├── Group.spec.ts
│ │ └── IconButton.spec.ts
│ ├── Checkbox
│ │ └── Checkbox.spec.ts
│ ├── Chip
│ │ └── Chip.spec.ts
│ ├── Divider
│ │ └── Divider.spec.ts
│ ├── Icon
│ │ └── Icon.spec.ts
│ ├── Input
│ │ ├── Group.spec.ts
│ │ └── Input.spec.ts
│ ├── Pagination
│ │ └── Pagination.spec.ts
│ ├── Progress
│ │ └── Progress.spec.ts
│ ├── Radio
│ │ └── Radio.spec.ts
│ ├── Range
│ │ └── Range.spec.ts
│ ├── Select
│ │ └── Select.spec.ts
│ ├── Steps
│ │ └── Steps.spec.ts
│ ├── Switch
│ │ └── Switch.spec.ts
│ ├── Tabs
│ │ └── Tabs.spec.ts
│ ├── Toast
│ │ └── Toast.spec.ts
│ └── Transition
│ │ └── Transition.spec.ts
├── layouts
│ ├── Card
│ │ └── Card.spec.ts
│ ├── Code
│ │ └── Code.spec.ts
│ ├── Container
│ │ └── Container.spec.ts
│ ├── Dropdown
│ │ └── Dropdown.spec.ts
│ ├── Empty
│ │ └── Empty.spec.ts
│ ├── Figure
│ │ └── Figure.spec.ts
│ ├── Form
│ │ ├── Form.spec.ts
│ │ └── FormGroup.spec.ts
│ ├── Grid
│ │ ├── Col.spec.ts
│ │ └── Grid.spec.ts
│ ├── Hero
│ │ └── Hero.spec.ts
│ ├── Modal
│ │ └── Modal.spec.ts
│ ├── Navbar
│ │ └── Navbar.spec.ts
│ ├── Panel
│ │ └── Panel.spec.ts
│ ├── Popover
│ │ └── Popover.spec.ts
│ ├── Sidebar
│ │ └── Sidebar.spec.ts
│ └── Tile
│ │ └── Tile.spec.ts
└── setup
│ ├── preprocess.js
│ ├── register.js
│ ├── slots.js
│ ├── svelteconfig.js
│ ├── testenv.js
│ └── transformer.js
├── tsconfig.json
└── vite.config.js
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | end_of_line = lf
5 | insert_final_newline = true
6 |
7 | [*.{js,css,html,json,svelte,yaml}]
8 | charset = utf-8
9 | indent_style = tab
10 | indent_size = 4
11 | trim_trailing_whitespace = true
12 | max_line_length = 100
13 |
--------------------------------------------------------------------------------
/.eslintrc.cjs:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | parser: '@typescript-eslint/parser',
4 | extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended', 'prettier'],
5 | plugins: ['svelte3', '@typescript-eslint'],
6 | ignorePatterns: ['*.cjs'],
7 | overrides: [{ files: ['*.svelte'], processor: 'svelte3/svelte3' }],
8 | settings: {
9 | 'svelte3/typescript': () => require('typescript')
10 | },
11 | parserOptions: {
12 | sourceType: 'module',
13 | ecmaVersion: 2020
14 | },
15 | env: {
16 | browser: true,
17 | es2017: true,
18 | node: true
19 | }
20 | };
21 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | /build
4 | /.svelte-kit
5 | /package
6 | .env
7 | .env.*
8 | !.env.example
9 |
--------------------------------------------------------------------------------
/.husky/pre-commit:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | . "$(dirname "$0")/_/husky.sh"
3 |
4 | npm run format
5 |
--------------------------------------------------------------------------------
/.npmrc:
--------------------------------------------------------------------------------
1 | engine-strict=true
2 |
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "tabWidth": 4,
3 | "semi": true,
4 | "singleQuote": true,
5 | "svelteSortOrder": "options-markup-scripts-styles",
6 | "svelteStrictMode": false,
7 | "svelteAllowShorthand": true,
8 | "svelteIndentScriptAndStyle": true,
9 | "plugins": [
10 | "prettier-plugin-svelte"
11 | ]
12 | }
13 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright 2021-2022 BASF SE
2 |
3 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
4 |
5 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
6 |
7 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
8 |
9 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
10 |
11 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Svelte-spectre
2 |
3 | [](https://www.npmjs.com/package/svelte-spectre)
4 | [](https://www.npmjs.com/package/svelte-spectre)
5 | [](https://github.com/basf/svelte-spectre/issues)
6 |
7 | UI-kit based on [spectre.css](https://picturepan2.github.io/spectre/) and powered by SvelteJS. See the [documentation](https://kit.optimade.science), which is also a component explorer (storybook).
8 |
9 | ### Requirements
10 |
11 | - `node -v >= 15`
12 | - `npm -v >= 7`
13 |
14 | ## Installation
15 |
16 | ```bash
17 | npm install
18 | ```
19 |
20 | ## Building package
21 |
22 | This builds the GUI components in a `package` folder:
23 |
24 | ```bash
25 | npm run package
26 | ```
27 |
28 | ## Developing
29 |
30 | This serves a [demonstration website](https://kit.optimade.science):
31 |
32 | ```bash
33 | npm run dev
34 |
35 | # or start the server and open the app in a new browser tab
36 | npm run dev -- --open
37 | ```
38 |
39 | The demo website lives in a separate repo https://github.com/tilde-lab/svelte-spectre-storybook.
40 |
41 | ## Integration
42 |
43 | Before creating a production version of your app, install an [adapter](https://kit.svelte.dev/docs#adapters) for your target environment. Then run:
44 |
45 | ```bash
46 | npm run build
47 | ```
48 |
49 | You can preview the built app with `npm run preview`, regardless of whether you installed an adapter. This should _not_ be used to serve your app in production.
50 |
51 | ## License
52 |
53 | Copyright 2024-2025 Materials Platform for Data Science LLC
54 |
55 | Copyright 2021-2023 BASF SE
56 |
57 | BSD 3-Clause
58 |
--------------------------------------------------------------------------------
/mdsvex.config.js:
--------------------------------------------------------------------------------
1 | const config = {
2 | extensions: ['.svelte.md', '.md', '.svx'],
3 | smartypants: {
4 | dashes: 'oldschool',
5 | },
6 | remarkPlugins: [],
7 | rehypePlugins: [],
8 | };
9 |
10 | export default config;
11 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "svelte-spectre",
3 | "version": "0.4.19",
4 | "description": "UI-kit based on spectre.css and powered by SvelteJS",
5 | "main": "./package/index.js",
6 | "files": [
7 | "package/"
8 | ],
9 | "type": "module",
10 | "scripts": {
11 | "dev": "vite dev",
12 | "build": "vite build",
13 | "preview": "vite preview",
14 | "package": "svelte-package && sass src/lib/spectre.scss package/spectre.css --style=compressed --no-source-map --quiet-deps && prettier --ignore-path .gitignore --write \"{,package/**/}*.{js,ts,md,svelte}\"",
15 | "check": "svelte-check --tsconfig ./tsconfig.json",
16 | "check:watch": "svelte-check --tsconfig ./tsconfig.json --watch",
17 | "lint": "npm run format && eslint --ignore-path .gitignore .",
18 | "format": "prettier --ignore-path .gitignore --write \"{,(src|tests|package)/**/}*.{js,ts,md,svelte}\"",
19 | "test": "uvu tests '.spec.ts' -r tsm -r tests/setup/register -i setup",
20 | "prepublishOnly": "npm run package",
21 | "husky:init": "npx husky install",
22 | "prepare": "husky install"
23 | },
24 | "author": "Alexander Volkov",
25 | "license": "BSD 3-Clause",
26 | "repository": {
27 | "type": "git",
28 | "url": "git+https://github.com/basf/svelte-spectre.git"
29 | },
30 | "engines": {
31 | "node": ">= 14"
32 | },
33 | "devDependencies": {
34 | "@poppanator/sveltekit-svg": "^0.3.4",
35 | "@sveltejs/adapter-static": "^1.0.0-next.43",
36 | "@sveltejs/kit": "^1.0.0-next.504",
37 | "@sveltejs/package": "1.0.0-next.3",
38 | "@types/jsdom": "^20.0.0",
39 | "@typescript-eslint/eslint-plugin": "^5.38.1",
40 | "@typescript-eslint/parser": "^5.38.1",
41 | "eslint": "^8.24.0",
42 | "eslint-config-prettier": "^8.5.0",
43 | "eslint-plugin-svelte3": "^4.0.0",
44 | "husky": "^8.0.1",
45 | "jsdom": "^20.0.0",
46 | "mdsvex": "^0.10.6",
47 | "pirates": "^4.0.5",
48 | "prettier": "^2.7.1",
49 | "prettier-plugin-svelte": "^2.7.1",
50 | "sass": "^1.55.0",
51 | "spectre.css": "^0.5.9",
52 | "svelte": "^3.50.1",
53 | "svelte-check": "^2.9.1",
54 | "svelte-preprocess": "^4.10.7",
55 | "svelte2tsx": "^0.5.19",
56 | "tslib": "^2.4.0",
57 | "tsm": "^2.2.2",
58 | "typescript": "~4.7.4",
59 | "uvu": "^0.5.6",
60 | "vite": "^3.1.3"
61 | },
62 | "dependencies": {
63 | "@ctrl/tinycolor": "^3.4.1"
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/src/global.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | declare module '*.svg?src' {
3 | const content: string;
4 | export default content;
5 | }
6 |
7 | declare module '*.svg?component' {
8 | const content: string;
9 | export default content;
10 | }
11 |
12 | declare module '*.svg?url' {
13 | const content: string;
14 | export default content;
15 | }
16 |
--------------------------------------------------------------------------------
/src/lib/components/Accordion/Accordion.svelte:
--------------------------------------------------------------------------------
1 |
2 |
5 | {#if opened}
6 |
7 |
8 |
9 | {/if}
10 |
11 |
12 |
17 |
18 |
52 |
53 |
79 |
--------------------------------------------------------------------------------
/src/lib/components/Accordion/Accordioner.svelte:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
--------------------------------------------------------------------------------
/src/lib/components/Accordion/index.ts:
--------------------------------------------------------------------------------
1 | export * from './Accordion.svelte';
2 | export { default } from './Accordion.svelte';
3 | export { default as Accordion } from './Accordion.svelte';
4 | export { default as Accordioner } from './Accordioner.svelte';
5 |
--------------------------------------------------------------------------------
/src/lib/components/Autocomplete/index.ts:
--------------------------------------------------------------------------------
1 | export * from './Autocomplete.svelte';
2 | export { default } from './Autocomplete.svelte';
3 | export { default as Autocomplete } from './Autocomplete.svelte';
4 |
--------------------------------------------------------------------------------
/src/lib/components/Autocomplete/utils.ts:
--------------------------------------------------------------------------------
1 | import type { Color } from '../../types/text';
2 |
3 | export type Item = {
4 | index?: number;
5 | label?: string;
6 | value?: any;
7 | group?: string;
8 | type?: Color | string;
9 | style?: string;
10 | };
11 |
12 | function calcSuggestion(
13 | predefined: Item[],
14 | selected: Item[],
15 | value: string
16 | ): Item[] {
17 | return predefined.filter(
18 | (p) =>
19 | stringIndex(p.label, value) >= 0 &&
20 | !selected.some((s) => s.index === p.index)
21 | );
22 | }
23 |
24 | function calcPrompt(suggested: Item[], value: string, active: number): string {
25 | return stringIndex(suggested[active]?.label, value) === 0
26 | ? suggested[active].label
27 | : '';
28 | }
29 |
30 | function stringIndex(item: string, value: string): number {
31 | const regexp = new RegExp(value, 'i');
32 | return item?.search(regexp);
33 | }
34 |
35 | function stringMatch(item: string, value: string): string {
36 | const regex = new RegExp(value, 'i');
37 | return item?.match(regex).join('');
38 | }
39 |
40 | function markSuggestion(item: string, value: string): string {
41 | const match = stringMatch(item, value);
42 | return item.replace(match, `${match} `);
43 | }
44 |
45 | function createObject(
46 | item: string,
47 | items: string[] | Item[],
48 | index?: number
49 | ): Item {
50 | return {
51 | index: index >= 0 ? index : items.length,
52 | value: item,
53 | label: `${item || ''}`,
54 | };
55 | }
56 |
57 | function createIndexes(items: Item[]): Item[] {
58 | return items?.some((item) => !item?.hasOwnProperty('index'))
59 | ? items.map((item: Item, i) => ({ ...item, index: i }))
60 | : items;
61 | }
62 |
63 | function makeGroups(items: Item[]): any[] | Item {
64 | if (!items || !items.length) {
65 | console.warn(`Autocomplete haven't items`);
66 | return [];
67 | } else {
68 | return items.reduce((a, c) => {
69 | a[c.group] = a[c.group] || [];
70 | a[c.group]?.push(c);
71 | return a;
72 | }, {});
73 | }
74 | }
75 |
76 | export {
77 | calcSuggestion,
78 | calcPrompt,
79 | createObject,
80 | createIndexes,
81 | markSuggestion,
82 | makeGroups,
83 | stringIndex,
84 | stringMatch,
85 | };
86 |
--------------------------------------------------------------------------------
/src/lib/components/Avatar/Avatar.svelte:
--------------------------------------------------------------------------------
1 |
12 |
13 |
14 | {#if status}
15 |
16 | {:else if $$slots.sub}
17 |
18 |
19 |
20 | {/if}
21 | {#if caption || $$slots.caption}
22 |
23 | {name}
24 |
25 | {/if}
26 |
27 |
28 |
39 |
40 |
62 |
63 |
106 |
--------------------------------------------------------------------------------
/src/lib/components/Avatar/index.ts:
--------------------------------------------------------------------------------
1 | export * from './Avatar.svelte';
2 | export { default } from './Avatar.svelte';
3 | export { default as Avatar } from './Avatar.svelte';
4 |
--------------------------------------------------------------------------------
/src/lib/components/Badge/Badge.svelte:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
8 |
9 |
13 |
14 |
28 |
--------------------------------------------------------------------------------
/src/lib/components/Badge/action.ts:
--------------------------------------------------------------------------------
1 | export default function addBadge(node: HTMLElement, badge: string) {
2 | function update(badge: string) {
3 | if (!badge && !badge?.length) return destroy();
4 | node.classList.add('badge');
5 | badge.length > 0
6 | ? node.setAttribute('data-badge', badge)
7 | : node.removeAttribute('data-badge');
8 | }
9 | function destroy() {
10 | node.classList.remove('badge');
11 | node.removeAttribute('data-badge');
12 | }
13 | update(badge);
14 | return { update, destroy };
15 | }
16 |
--------------------------------------------------------------------------------
/src/lib/components/Badge/index.ts:
--------------------------------------------------------------------------------
1 | export * from './Badge.svelte';
2 | export { default } from './Badge.svelte';
3 | export { default as Badge } from './Badge.svelte';
4 | export { default as badge } from './action';
5 |
--------------------------------------------------------------------------------
/src/lib/components/Bars/Bars.svelte:
--------------------------------------------------------------------------------
1 |
2 | {#each items as item, i}
3 | {#if !item.invisible}
4 |
12 | {labled ? item.label || item.value : ''}
13 |
14 | {/if}
15 | {/each}
16 |
17 |
18 |
33 |
34 |
87 |
88 |
138 |
--------------------------------------------------------------------------------
/src/lib/components/Bars/index.ts:
--------------------------------------------------------------------------------
1 | export * from './Bars.svelte';
2 | export { default } from './Bars.svelte';
3 | export { default as Bars } from './Bars.svelte';
4 |
--------------------------------------------------------------------------------
/src/lib/components/Breadcrumbs/Breadcrumbs.svelte:
--------------------------------------------------------------------------------
1 |
10 |
11 |
19 |
20 |
23 |
24 |
27 |
--------------------------------------------------------------------------------
/src/lib/components/Breadcrumbs/index.ts:
--------------------------------------------------------------------------------
1 | export * from './Breadcrumbs.svelte';
2 | export { default } from './Breadcrumbs.svelte';
3 | export { default as Breadcrumbs } from './Breadcrumbs.svelte';
4 |
--------------------------------------------------------------------------------
/src/lib/components/Button/Button.svelte:
--------------------------------------------------------------------------------
1 | {#if href}
2 |
21 |
22 |
23 | {:else}
24 |
42 |
43 |
44 | {/if}
45 |
46 |
55 |
56 |
71 |
72 |
106 |
--------------------------------------------------------------------------------
/src/lib/components/Button/Group.svelte:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
8 |
9 |
14 |
--------------------------------------------------------------------------------
/src/lib/components/Button/IconButton.svelte:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
14 |
15 |
20 |
--------------------------------------------------------------------------------
/src/lib/components/Button/index.ts:
--------------------------------------------------------------------------------
1 | export * from './Button.svelte';
2 | export { default } from './Button.svelte';
3 | export { default as Button } from './Button.svelte';
4 | export { default as ButtonGroup } from './Group.svelte';
5 | export { default as IconButton } from './IconButton.svelte';
6 |
--------------------------------------------------------------------------------
/src/lib/components/Checkbox/Checkbox.svelte:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
10 |
11 |
12 |
19 |
20 |
28 |
29 |
32 |
--------------------------------------------------------------------------------
/src/lib/components/Checkbox/index.ts:
--------------------------------------------------------------------------------
1 | export * from './Checkbox.svelte';
2 | export { default } from './Checkbox.svelte';
3 | export { default as Checkbox } from './Checkbox.svelte';
4 |
--------------------------------------------------------------------------------
/src/lib/components/Chip/Chip.svelte:
--------------------------------------------------------------------------------
1 |
2 | {#if avatar}
3 |
4 |
5 |
6 | {/if}
7 |
8 | {#if closable}
9 |
dispatch('close', 'chip close')}
13 | />
14 | {/if}
15 |
16 |
17 |
26 |
27 |
38 |
39 |
94 |
--------------------------------------------------------------------------------
/src/lib/components/Chip/index.ts:
--------------------------------------------------------------------------------
1 | export * from './Chip.svelte';
2 | export { default } from './Chip.svelte';
3 | export { default as Chip } from './Chip.svelte';
4 |
--------------------------------------------------------------------------------
/src/lib/components/Divider/Divider.svelte:
--------------------------------------------------------------------------------
1 |
11 |
12 |
18 |
19 |
25 |
26 |
51 |
--------------------------------------------------------------------------------
/src/lib/components/Divider/index.ts:
--------------------------------------------------------------------------------
1 | export * from './Divider.svelte';
2 | export { default } from './Divider.svelte';
3 | export { default as Divider } from './Divider.svelte';
4 |
--------------------------------------------------------------------------------
/src/lib/components/Icon/index.ts:
--------------------------------------------------------------------------------
1 | export * from './Icon.svelte';
2 | export { default } from './Icon.svelte';
3 | export { default as Icon } from './Icon.svelte';
4 |
--------------------------------------------------------------------------------
/src/lib/components/Input/Group.svelte:
--------------------------------------------------------------------------------
1 |
2 | {#if $$slots.addon}
3 |
4 | {/if}
5 | {#if $$slots.default}
6 |
7 | {/if}
8 | {#if $$slots.button}
9 |
10 | {/if}
11 |
12 |
13 |
17 |
18 |
22 |
23 |
26 |
--------------------------------------------------------------------------------
/src/lib/components/Input/Input.svelte:
--------------------------------------------------------------------------------
1 | {#if $$slots.default}
2 |
3 |
4 |
5 |
6 |
7 | {/if}
8 |
14 | {#if rows > 1}
15 |
27 | {:else}
28 |
39 | {/if}
40 | {#if $$slots.iconLeft}
41 |
42 |
43 |
44 | {/if}
45 | {#if $$slots.iconRight}
46 |
47 |
48 |
49 | {/if}
50 | {#if $$slots.hint}
51 |
52 |
53 |
54 | {/if}
55 |
56 | {#if options.length}
57 |
58 | {#each options as value}
59 | {/each}
60 |
61 | {/if}
62 |
63 |
72 |
73 |
84 |
85 |
124 |
--------------------------------------------------------------------------------
/src/lib/components/Input/index.ts:
--------------------------------------------------------------------------------
1 | export * from './Input.svelte';
2 | export { default } from './Input.svelte';
3 | export { default as Input } from './Input.svelte';
4 | export { default as InputGroup } from './Group.svelte';
5 |
--------------------------------------------------------------------------------
/src/lib/components/Menu/Menu.svelte:
--------------------------------------------------------------------------------
1 |
52 |
53 |
70 |
71 |
84 |
85 |
126 |
--------------------------------------------------------------------------------
/src/lib/components/Menu/index.ts:
--------------------------------------------------------------------------------
1 | export * from './Menu.svelte';
2 | export { default } from './Menu.svelte';
3 | export { default as Menu } from './Menu.svelte';
4 |
--------------------------------------------------------------------------------
/src/lib/components/Meter/index.ts:
--------------------------------------------------------------------------------
1 | export * from './Meter.svelte';
2 | export { default } from './Meter.svelte';
3 | export { default as Meter } from './Meter.svelte';
4 |
--------------------------------------------------------------------------------
/src/lib/components/Pagination/index.ts:
--------------------------------------------------------------------------------
1 | export * from './Pagination.svelte';
2 | export { default } from './Pagination.svelte';
3 | export { default as Pagination } from './Pagination.svelte';
4 |
--------------------------------------------------------------------------------
/src/lib/components/PeriodicTable/chemical_content.json:
--------------------------------------------------------------------------------
1 | {
2 | "period 1": ["H", "He"],
3 | "period 2": ["Li", "Be", "B", "C", "N", "O", "F", "Ne"],
4 | "period 3": ["Na", "Mg", "Al", "Si", "P", "S", "Cl", "Ar"],
5 | "period 4": ["K", "Ca", "Sc", "Ti", "V", "Cr", "Mn", "Fe", "Co", "Ni", "Cu", "Zn", "Ga", "Ge", "As", "Se", "Br", "Kr"],
6 | "period 5": ["Rb", "Sr", "Y", "Zr", "Nb", "Mo", "Tc", "Ru", "Rh", "Pd", "Ag", "Cd", "In", "Sn", "Sb", "Te", "I", "Xe"],
7 | "period 6": ["Cs", "Ba", "Lu", "Hf", "Ta", "W", "Re", "Os", "Ir", "Pt", "Au", "Hg", "Tl", "Pb", "Bi", "Po", "At", "Rn"],
8 | "period 7": ["Fr", "Ra", "Lr"],
9 | "lanthanide": ["La", "Ce", "Pr", "Nd", "Pm", "Sm", "Eu", "Gd", "Tb", "Dy", "Ho", "Er", "Tm", "Yb"],
10 | "actinide": ["Ac", "Th", "Pa", "U", "Np", "Pu", "Am", "Cm", "Bk", "Cf", "Es", "Fm", "Md", "No"],
11 | "alkali": ["H", "Li", "Na", "K", "Rb", "Cs", "Fr"],
12 | "alkaline": ["Be", "Mg", "Ca", "Sr", "Ba", "Ra"],
13 | "group 3": ["Sc", "Y", "Lu", "Lr"],
14 | "group 4": ["Ti", "Zr", "Hf"],
15 | "group 5": ["V", "Nb", "Ta"],
16 | "group 6": ["Cr", "Mo", "W"],
17 | "group 7": ["Mn", "Tc", "Re"],
18 | "group 8": ["Fe", "Ru", "Os"],
19 | "group 9": ["Co", "Rh", "Ir"],
20 | "group 10": ["Ni", "Pd", "Pt"],
21 | "group 11": ["Cu", "Ag", "Au"],
22 | "group 12": ["Zn", "Cd", "Hg"],
23 | "triels": ["B", "Al", "Ga", "In", "Tl"],
24 | "tetrels": ["C", "Si", "Ge", "Sn", "Pb"],
25 | "pnictogen": ["N", "P", "As", "Sb", "Bi"],
26 | "chalcogen": ["O", "S", "Se", "Te", "Po"],
27 | "halogen": ["F", "Cl", "Br", "I", "At"],
28 | "noble gas": ["He", "Ne", "Ar", "Kr", "Xe", "Rn"]
29 | }
--------------------------------------------------------------------------------
/src/lib/components/PeriodicTable/index.ts:
--------------------------------------------------------------------------------
1 | export * from './PeriodicTable.svelte';
2 | export { default } from './PeriodicTable.svelte';
3 | export { default as PeriodicTable } from './PeriodicTable.svelte';
4 |
--------------------------------------------------------------------------------
/src/lib/components/Progress/Progress.svelte:
--------------------------------------------------------------------------------
1 |
8 |
9 |
13 |
14 |
20 |
21 |
54 |
--------------------------------------------------------------------------------
/src/lib/components/Progress/index.ts:
--------------------------------------------------------------------------------
1 | export * from './Progress.svelte';
2 | export { default } from './Progress.svelte';
3 | export { default as Progress } from './Progress.svelte';
4 |
--------------------------------------------------------------------------------
/src/lib/components/Radio/Radio.svelte:
--------------------------------------------------------------------------------
1 | {#if label}
2 | {label}
3 | {/if}
4 | {#each radios as radio, i}
5 |
11 |
12 | {radio.label}
13 |
14 | {/each}
15 |
16 |
23 |
24 |
33 |
34 |
37 |
--------------------------------------------------------------------------------
/src/lib/components/Radio/index.ts:
--------------------------------------------------------------------------------
1 | export * from './Radio.svelte';
2 | export { default } from './Radio.svelte';
3 | export { default as Radio } from './Radio.svelte';
4 |
--------------------------------------------------------------------------------
/src/lib/components/Range/Range.svelte:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
12 |
13 |
20 |
21 |
30 |
31 |
115 |
--------------------------------------------------------------------------------
/src/lib/components/Range/index.ts:
--------------------------------------------------------------------------------
1 | export * from './Range.svelte';
2 | export { default } from './Range.svelte';
3 | export { default as Range } from './Range.svelte';
4 |
--------------------------------------------------------------------------------
/src/lib/components/Select/Select.svelte:
--------------------------------------------------------------------------------
1 | {#if $$slots.label}
2 |
3 |
4 |
5 |
6 |
7 | {/if}
8 |
9 | {#if multiple}
10 |
25 | {#if placeholder}
26 | {placeholder}
27 | {/if}
28 | {#each options as option, index}
29 |
30 | {getLabel(option, index)}
31 |
32 | {/each}
33 |
34 | {:else}
35 |
49 | {#if placeholder}
50 | {placeholder}
51 | {/if}
52 | {#each options as option, index}
53 |
54 | {getLabel(option, index)}
55 |
56 | {/each}
57 |
58 | {/if}
59 |
60 |
73 |
74 |
109 |
110 |
113 |
--------------------------------------------------------------------------------
/src/lib/components/Select/index.ts:
--------------------------------------------------------------------------------
1 | export * from './Select.svelte';
2 | export { default } from './Select.svelte';
3 | export { default as Select } from './Select.svelte';
4 |
--------------------------------------------------------------------------------
/src/lib/components/Steps/Steps.svelte:
--------------------------------------------------------------------------------
1 |
13 |
14 |
21 |
22 |
26 |
27 |
32 |
--------------------------------------------------------------------------------
/src/lib/components/Steps/index.ts:
--------------------------------------------------------------------------------
1 | export * from './Steps.svelte';
2 | export { default } from './Steps.svelte';
3 | export { default as Steps } from './Steps.svelte';
4 |
--------------------------------------------------------------------------------
/src/lib/components/Switch/Switch.svelte:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
10 |
11 |
12 |
19 |
20 |
27 |
28 |
31 |
--------------------------------------------------------------------------------
/src/lib/components/Switch/index.ts:
--------------------------------------------------------------------------------
1 | export * from './Switch.svelte';
2 | export { default } from './Switch.svelte';
3 | export { default as Switch } from './Switch.svelte';
4 |
--------------------------------------------------------------------------------
/src/lib/components/Tabs/Tabs.svelte:
--------------------------------------------------------------------------------
1 |
26 |
27 |
43 |
44 |
88 |
89 |
130 |
--------------------------------------------------------------------------------
/src/lib/components/Tabs/index.ts:
--------------------------------------------------------------------------------
1 | export * from './Tabs.svelte';
2 | export { default } from './Tabs.svelte';
3 | export { default as Tabs } from './Tabs.svelte';
4 |
--------------------------------------------------------------------------------
/src/lib/components/Toast/Toaster.svelte:
--------------------------------------------------------------------------------
1 | {#if $toast.length}
2 |
3 | {#each positions as pos}
4 |
5 | {#each toasted(pos) as toastItem, i (toastItem.id)}
6 |
7 |
8 | {#if toastItem.title}{toastItem.title} {/if}
9 | {#if toastItem.msg}{toastItem.msg}
{/if}
10 |
11 |
12 | {/each}
13 |
14 | {/each}
15 |
16 | {/if}
17 |
18 |
26 |
27 |
40 |
41 |
98 |
--------------------------------------------------------------------------------
/src/lib/components/Toast/index.ts:
--------------------------------------------------------------------------------
1 | export * from './Toast.svelte';
2 | export { default } from './Toast.svelte';
3 | export { default as Toast } from './Toast.svelte';
4 | export { default as Toaster } from './Toaster.svelte';
5 | export * from './toast';
6 |
--------------------------------------------------------------------------------
/src/lib/components/Toast/positions.ts:
--------------------------------------------------------------------------------
1 | export type Pos =
2 | | ''
3 | | 'top_center'
4 | | 'top_right'
5 | | 'center_right'
6 | | 'bottom_right'
7 | | 'bottom_center'
8 | | 'bottom_left'
9 | | 'center_left'
10 | | 'top_left'
11 | | 'center_center';
12 |
13 | export const positions: Pos[] = [
14 | 'top_center',
15 | 'top_right',
16 | 'center_right',
17 | 'bottom_right',
18 | 'bottom_center',
19 | 'bottom_left',
20 | 'center_left',
21 | 'top_left',
22 | 'center_center',
23 | ];
24 |
--------------------------------------------------------------------------------
/src/lib/components/Toast/timer.ts:
--------------------------------------------------------------------------------
1 | export interface Timer extends ReturnType {
2 | set(remaining: number): Function;
3 | pause(): Function;
4 | resume(): Function;
5 | clear(): Function;
6 | }
7 |
8 | export function Timer(callback: Function, delay: number): void {
9 | let timerId: number,
10 | start: number,
11 | remaining: number = delay;
12 |
13 | const set = (remaining: number) => {
14 | clearTimeout(timerId);
15 | timerId = setTimeout(callback, remaining);
16 | };
17 |
18 | const pause = () => {
19 | clearTimeout(timerId);
20 | remaining -= Date.now() - start;
21 | };
22 |
23 | const resume = () => {
24 | start = Date.now();
25 | clearTimeout(timerId);
26 | timerId = setTimeout(callback, remaining);
27 | };
28 |
29 | const clear = () => {
30 | clearTimeout(timerId);
31 | };
32 |
33 | resume();
34 |
35 | return { set, pause, resume, clear, timerId };
36 | }
37 |
--------------------------------------------------------------------------------
/src/lib/components/Toast/toast.ts:
--------------------------------------------------------------------------------
1 | import { writable } from 'svelte/store';
2 |
3 | import type { Icons } from '../../types/icons';
4 | import type { Color } from '../../types/bg';
5 | import type { Pos } from './positions';
6 |
7 | interface ToastItem {
8 | id?: number;
9 | type?: Color;
10 | title?: string;
11 | msg?: string;
12 | icon?: Icons;
13 | closable?: boolean;
14 | timeout?: number;
15 | invert?: boolean;
16 | reverse?: boolean;
17 | pos?: Pos;
18 | }
19 |
20 | export type { Pos, ToastItem };
21 |
22 | const defaults: ToastItem = { closable: false, pos: 'top_center' };
23 |
24 | function createToast() {
25 | const { subscribe, set, update } = writable([]);
26 |
27 | let id = 0;
28 |
29 | const send = (toast: ToastItem = {}) => {
30 | toast.id = id++;
31 | update((state) => [...state, { ...defaults, ...toast }]);
32 | };
33 | const close = (id: number) => {
34 | update((state) => [...state.filter((t) => t.id !== id)]);
35 | };
36 | const clear = () => set([]);
37 |
38 | return {
39 | subscribe,
40 | send,
41 | close,
42 | clear,
43 | default: (toast: ToastItem = {}) =>
44 | send({ msg: 'default', icon: 'message', ...toast }),
45 | error: (toast: ToastItem = {}) =>
46 | send({ type: 'error', icon: 'stop', ...toast }),
47 | warning: (toast: ToastItem = {}) =>
48 | send({ type: 'warning', icon: 'mail', ...toast }),
49 | primary: (toast: ToastItem = {}) =>
50 | send({ type: 'primary', icon: 'flag', ...toast }),
51 | success: (toast: ToastItem = {}) =>
52 | send({ type: 'success', icon: 'check', ...toast }),
53 | };
54 | }
55 |
56 | export const toast = createToast();
57 |
--------------------------------------------------------------------------------
/src/lib/components/Transition/Transition.svelte:
--------------------------------------------------------------------------------
1 | {#key key}
2 |
3 |
4 |
5 | {/key}
6 |
7 |
24 |
25 |
42 |
--------------------------------------------------------------------------------
/src/lib/components/Transition/index.ts:
--------------------------------------------------------------------------------
1 | export * from './Transition.svelte';
2 | export { default } from './Transition.svelte';
3 | export { default as Transition } from './Transition.svelte';
4 |
--------------------------------------------------------------------------------
/src/lib/components/index.ts:
--------------------------------------------------------------------------------
1 | export * from './Accordion/';
2 | export * from './Autocomplete/';
3 | export * from './Avatar/';
4 | export * from './Badge/';
5 | export * from './Bars/';
6 | export * from './Breadcrumbs/';
7 | export * from './Button/';
8 | export * from './Checkbox/';
9 | export * from './Chip/';
10 | export * from './Divider/';
11 | export * from './Icon/';
12 | export * from './Input/';
13 | export * from './Menu/';
14 | export * from './Meter/';
15 | export * from './Pagination/';
16 | export * from './PeriodicTable/';
17 | export * from './Progress/';
18 | export * from './Radio';
19 | export * from './Range';
20 | export * from './Select';
21 | export * from './Steps/';
22 | export * from './Switch/';
23 | export * from './Tabs/';
24 | export * from './Toast/';
25 | export * from './Transition/';
26 |
--------------------------------------------------------------------------------
/src/lib/dark.scss:
--------------------------------------------------------------------------------
1 | $dark-background: darken($dark-color, 5%);
2 | $dark-text: darken($light-color, 5%);
3 | $dark-secondary: mix($dark-color, $primary-color, 90%);
4 | $dark-shadow: darken($dark-background, 10%);
5 | $dark-border: darken($border-color, 10%);
6 | $dark-overlay: rgba($dark-background, 0.69);
7 | $dark-code: mix($dark-color, $code-color, 90%);
8 | $dark-highlight: darken($highlight-color, 50%);
9 |
--------------------------------------------------------------------------------
/src/lib/helpers/actions.ts:
--------------------------------------------------------------------------------
1 | // addClass to any element
2 | function addClass(node: HTMLElement, classes: string[]) {
3 | node.classList.add(...classes);
4 | }
5 |
6 | export { addClass };
7 |
--------------------------------------------------------------------------------
/src/lib/helpers/str_to_rgb.ts:
--------------------------------------------------------------------------------
1 | export function str_to_rgb(input_str: string): string {
2 | const baseRed = 256,
3 | baseGreen = 256,
4 | baseBlue = 256;
5 | //lazy seeded random hack to get values from 0 - 256
6 | //for seed just take bitwise XOR of first two chars
7 | let seed = input_str.charCodeAt(0) ^ input_str.charCodeAt(1);
8 | const rand_1 = Math.abs(Math.sin(seed++) * 10000) % 256;
9 | const rand_2 = Math.abs(Math.sin(seed++) * 10000) % 256;
10 | const rand_3 = Math.abs(Math.sin(seed++) * 10000) % 256;
11 | const red = Math.round((rand_1 + baseRed) / 2);
12 | const green = Math.round((rand_2 + baseGreen) / 2);
13 | const blue = Math.round((rand_3 + baseBlue) / 2);
14 | return `rgb(${[red, green, blue].join(',')})`;
15 | }
16 |
--------------------------------------------------------------------------------
/src/lib/helpers/uuid.ts:
--------------------------------------------------------------------------------
1 | export default function uuid(): string {
2 | return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(
3 | /[xy]/g,
4 | function (c) {
5 | const r = (Math.random() * 16) | 0;
6 | const v = c === 'x' ? r : (r & 0x3) | 0x8;
7 | return v.toString(16);
8 | }
9 | );
10 | }
11 |
--------------------------------------------------------------------------------
/src/lib/index.ts:
--------------------------------------------------------------------------------
1 | export * from './components/';
2 | export * from './layouts/';
3 | export * from './Spectre.svelte';
4 | export { default } from './Spectre.svelte';
5 | export { default as Spectre } from './Spectre.svelte';
6 |
--------------------------------------------------------------------------------
/src/lib/layouts/Card/Card.svelte:
--------------------------------------------------------------------------------
1 |
10 | {#if $$slots.img && pos === 'top'}
11 |
12 |
13 |
14 | {/if}
15 |
27 | {#if $$slots.img && pos === 'middle'}
28 |
29 |
30 |
31 | {/if}
32 | {#if $$slots.default}
33 |
34 |
35 |
36 | {/if}
37 | {#if $$slots.img && pos === 'bottom'}
38 |
39 |
40 |
41 | {/if}
42 | {#if $$slots.footer}
43 |
46 | {/if}
47 |
48 |
49 |
52 |
53 |
61 |
62 |
91 |
--------------------------------------------------------------------------------
/src/lib/layouts/Card/index.ts:
--------------------------------------------------------------------------------
1 | export * from './Card.svelte';
2 | export { default } from './Card.svelte';
3 | export { default as Card } from './Card.svelte';
4 |
--------------------------------------------------------------------------------
/src/lib/layouts/Code/Code.svelte:
--------------------------------------------------------------------------------
1 | {#if action}
2 |
5 | {:else}
6 |
7 | {/if}
8 |
9 |
14 |
15 |
20 |
--------------------------------------------------------------------------------
/src/lib/layouts/Code/index.ts:
--------------------------------------------------------------------------------
1 | export * from './Code.svelte';
2 | export { default } from './Code.svelte';
3 | export { default as Code } from './Code.svelte';
4 |
--------------------------------------------------------------------------------
/src/lib/layouts/Container/Container.svelte:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
10 |
11 |
14 |
15 |
20 |
--------------------------------------------------------------------------------
/src/lib/layouts/Container/index.ts:
--------------------------------------------------------------------------------
1 | export * from './Container.svelte';
2 | export { default } from './Container.svelte';
3 | export { default as Container } from './Container.svelte';
4 |
--------------------------------------------------------------------------------
/src/lib/layouts/Dropdown/Dropdown.svelte:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
12 |
13 |
14 |
17 |
18 |
19 |
20 | (active = false)} />
21 |
22 |
43 |
44 |
97 |
--------------------------------------------------------------------------------
/src/lib/layouts/Dropdown/index.ts:
--------------------------------------------------------------------------------
1 | export * from './Dropdown.svelte';
2 | export { default } from './Dropdown.svelte';
3 | export { default as Dropdown } from './Dropdown.svelte';
4 |
--------------------------------------------------------------------------------
/src/lib/layouts/Empty/Empty.svelte:
--------------------------------------------------------------------------------
1 |
2 | {#if $$slots.icon}
3 |
4 |
5 |
6 | {/if}
7 | {#if $$slots.title}
8 |
9 |
10 |
11 | {/if}
12 | {#if $$slots.subtitle}
13 |
14 |
15 |
16 | {/if}
17 | {#if $$slots.action}
18 |
19 |
20 |
21 | {/if}
22 |
23 |
24 |
35 |
--------------------------------------------------------------------------------
/src/lib/layouts/Empty/index.ts:
--------------------------------------------------------------------------------
1 | export * from './Empty.svelte';
2 | export { default } from './Empty.svelte';
3 | export { default as Empty } from './Empty.svelte';
4 |
--------------------------------------------------------------------------------
/src/lib/layouts/Figure/Figure.svelte:
--------------------------------------------------------------------------------
1 |
2 |
3 |
10 |
11 | {#if $$slots.default}
12 |
13 | {/if}
14 |
15 |
16 |
20 |
21 |
26 |
27 |
35 |
--------------------------------------------------------------------------------
/src/lib/layouts/Figure/index.ts:
--------------------------------------------------------------------------------
1 | export * from './Figure.svelte';
2 | export { default } from './Figure.svelte';
3 | export { default as Figure } from './Figure.svelte';
4 |
--------------------------------------------------------------------------------
/src/lib/layouts/Form/Form.svelte:
--------------------------------------------------------------------------------
1 |
4 |
5 |
8 |
9 |
28 |
--------------------------------------------------------------------------------
/src/lib/layouts/Form/Group.svelte:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
10 |
14 |
15 |
19 |
20 |
90 |
--------------------------------------------------------------------------------
/src/lib/layouts/Form/index.ts:
--------------------------------------------------------------------------------
1 | export * from './Form.svelte';
2 | export { default } from './Form.svelte';
3 | export { default as Form } from './Form.svelte';
4 | export { default as FormGroup } from './Group.svelte';
5 |
--------------------------------------------------------------------------------
/src/lib/layouts/Grid/Col.svelte:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
9 |
10 |
25 |
26 |
31 |
--------------------------------------------------------------------------------
/src/lib/layouts/Grid/Grid.svelte:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
12 |
18 |
19 |
26 |
27 |
61 |
--------------------------------------------------------------------------------
/src/lib/layouts/Grid/index.ts:
--------------------------------------------------------------------------------
1 | export { default as Grid } from './Grid.svelte';
2 | export { default as Col } from './Col.svelte';
3 |
--------------------------------------------------------------------------------
/src/lib/layouts/Hero/Hero.svelte:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Hero title
5 | This is a hero example
6 |
7 |
8 |
9 |
10 |
16 |
17 |
22 |
23 |
32 |
--------------------------------------------------------------------------------
/src/lib/layouts/Hero/index.ts:
--------------------------------------------------------------------------------
1 | export * from './Hero.svelte';
2 | export { default } from './Hero.svelte';
3 | export { default as Hero } from './Hero.svelte';
4 |
--------------------------------------------------------------------------------
/src/lib/layouts/Modal/Modal.svelte:
--------------------------------------------------------------------------------
1 |
2 |
3 |
10 | {#if !custom}
11 |
12 | {/if}
13 |
14 |
15 |
18 |
19 |
20 |
21 |
24 |
25 |
26 |
27 |
41 |
42 |
61 |
62 |
116 |
--------------------------------------------------------------------------------
/src/lib/layouts/Modal/index.ts:
--------------------------------------------------------------------------------
1 | export * from './Modal.svelte';
2 | export { default } from './Modal.svelte';
3 | export { default as Modal } from './Modal.svelte';
4 |
--------------------------------------------------------------------------------
/src/lib/layouts/Navbar/Navbar.svelte:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
18 |
--------------------------------------------------------------------------------
/src/lib/layouts/Navbar/index.ts:
--------------------------------------------------------------------------------
1 | export * from './Navbar.svelte';
2 | export { default } from './Navbar.svelte';
3 | export { default as Navbar } from './Navbar.svelte';
4 |
--------------------------------------------------------------------------------
/src/lib/layouts/Panel/Panel.svelte:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
14 |
15 |
16 |
27 |
--------------------------------------------------------------------------------
/src/lib/layouts/Panel/index.ts:
--------------------------------------------------------------------------------
1 | export * from './Panel.svelte';
2 | export { default } from './Panel.svelte';
3 | export { default as Panel } from './Panel.svelte';
4 |
--------------------------------------------------------------------------------
/src/lib/layouts/Popover/Popover.svelte:
--------------------------------------------------------------------------------
1 |
12 |
13 |
16 |
17 |
22 |
23 |
37 |
--------------------------------------------------------------------------------
/src/lib/layouts/Popover/index.ts:
--------------------------------------------------------------------------------
1 | export * from './Popover.svelte';
2 | export { default } from './Popover.svelte';
3 | export { default as Popover } from './Popover.svelte';
4 |
--------------------------------------------------------------------------------
/src/lib/layouts/Sidebar/index.ts:
--------------------------------------------------------------------------------
1 | export * from './Sidebar.svelte';
2 | export { default } from './Sidebar.svelte';
3 | export { default as Sidebar } from './Sidebar.svelte';
4 |
--------------------------------------------------------------------------------
/src/lib/layouts/Tile/Tile.svelte:
--------------------------------------------------------------------------------
1 |
2 | {#if $$slots.icon}
3 |
4 |
5 |
6 | {/if}
7 |
8 | {#if $$slots.title}
9 |
10 |
11 |
12 | {/if}
13 | {#if $$slots.subtitle}
14 |
15 |
16 |
17 | {/if}
18 |
19 |
20 | {#if $$slots.action}
21 |
22 |
23 |
24 | {/if}
25 |
26 |
27 |
30 |
31 |
36 |
--------------------------------------------------------------------------------
/src/lib/layouts/Tile/index.ts:
--------------------------------------------------------------------------------
1 | export * from './Tile.svelte';
2 | export { default } from './Tile.svelte';
3 | export { default as Tile } from './Tile.svelte';
4 |
--------------------------------------------------------------------------------
/src/lib/layouts/Toggle/Toggle.svelte:
--------------------------------------------------------------------------------
1 |
2 | {#if toggle}
3 |
4 | {/if}
5 |
6 |
9 |
--------------------------------------------------------------------------------
/src/lib/layouts/Toggle/index.ts:
--------------------------------------------------------------------------------
1 | export * from './Toggle.svelte';
2 | export { default } from './Toggle.svelte';
3 | export { default as Toggle } from './Toggle.svelte';
4 |
--------------------------------------------------------------------------------
/src/lib/layouts/index.ts:
--------------------------------------------------------------------------------
1 | export * from './Card/';
2 | export * from './Code/';
3 | export * from './Container/';
4 | export * from './Dropdown/';
5 | export * from './Empty/';
6 | export * from './Figure/';
7 | export * from './Form/';
8 | export * from './Grid/';
9 | export * from './Hero/';
10 | export * from './Modal/';
11 | export * from './Navbar/';
12 | export * from './Panel/';
13 | export * from './Popover/';
14 | export * from './Sidebar';
15 | export * from './Tile/';
16 | export * from './Toggle/';
17 |
--------------------------------------------------------------------------------
/src/lib/types/asset.d.ts:
--------------------------------------------------------------------------------
1 | declare module '*.svg' {
2 | const content: any;
3 | export default content;
4 | }
5 |
--------------------------------------------------------------------------------
/src/lib/types/bg.d.ts:
--------------------------------------------------------------------------------
1 | export type Color =
2 | | 'initial'
3 | | 'primary'
4 | | 'secondary'
5 | | 'dark'
6 | | 'darked'
7 | | 'gray'
8 | | 'light'
9 | | 'success'
10 | | 'warning'
11 | | 'error'
12 | | '';
13 |
--------------------------------------------------------------------------------
/src/lib/types/const.ts:
--------------------------------------------------------------------------------
1 | export const SIZE = {
2 | xs: 16,
3 | sm: 24,
4 | md: 32,
5 | lg: 40,
6 | xl: 48,
7 | xxl: 64,
8 | } as const;
9 |
10 | export const ZOOM = {
11 | '1x': 1,
12 | '2x': 2,
13 | '3x': 3,
14 | '4x': 4,
15 | } as const;
16 |
--------------------------------------------------------------------------------
/src/lib/types/display.d.ts:
--------------------------------------------------------------------------------
1 | /* class should be prefixed with `d-{type}` */
2 | export type Display =
3 | | 'initial'
4 | | 'block'
5 | | 'inline'
6 | | 'inline-block'
7 | | 'flex'
8 | | 'inline-flex'
9 | | 'none'
10 | | 'hide'
11 | | 'visible'
12 | | 'invisible';
13 |
--------------------------------------------------------------------------------
/src/lib/types/icons.d.ts:
--------------------------------------------------------------------------------
1 | export type Icons =
2 | | 'arrow-up'
3 | | 'arrow-right'
4 | | 'arrow-down'
5 | | 'arrow-left'
6 | | 'upward'
7 | | 'forward'
8 | | 'downward'
9 | | 'back'
10 | | 'caret'
11 | | 'menu'
12 | | 'apps'
13 | | 'more-horiz'
14 | | 'more-vert'
15 | | 'resize-horiz'
16 | | 'resize-vert'
17 | | 'plus'
18 | | 'minus'
19 | | 'cross'
20 | | 'check'
21 | | 'stop'
22 | | 'shutdown'
23 | | 'refresh'
24 | | 'search'
25 | | 'flag'
26 | | 'bookmark'
27 | | 'edit'
28 | | 'delete'
29 | | 'share'
30 | | 'download'
31 | | 'upload'
32 | | 'copy'
33 | | 'mail'
34 | | 'people'
35 | | 'message'
36 | | 'photo'
37 | | 'time'
38 | | 'location'
39 | | 'link'
40 | | 'emoji'
41 | | 'home'
42 | | 'circle-check'
43 | | 'wifi'
44 | | 'audio'
45 | | 'tag'
46 | | ''
47 | | string;
48 |
--------------------------------------------------------------------------------
/src/lib/types/position.d.ts:
--------------------------------------------------------------------------------
1 | /* class should be prefixed with `float-{type}` */
2 | export type Float = 'none' | 'left' | 'right';
3 |
4 | /* class should be prefixed with `p-{type}` */
5 | export type Position =
6 | | 'static'
7 | | 'relative'
8 | | 'absolute'
9 | | 'fixed'
10 | | 'sticky'
11 | | 'centered';
12 |
13 | /* class should be postfixed with `{type}-1` or `{type}-2` */
14 | export type Margin = 'm' | 'mt' | 'mb' | 'mx' | 'my' | false;
15 | export type Padding = 'p' | 'pt' | 'pb' | 'px' | 'py' | false;
16 |
17 | /* global offset rules */
18 | export type Offset =
19 | | 'my-0'
20 | | 'my-1'
21 | | 'my-2'
22 | | 'my--1'
23 | | 'my--2'
24 | | 'my-auto'
25 | | 'mx-0'
26 | | 'mx-1'
27 | | 'mx-2'
28 | | 'mx--1'
29 | | 'mx--2'
30 | | 'mx-auto'
31 | | 'mt-0'
32 | | 'mt-1'
33 | | 'mt-2'
34 | | 'mt--1'
35 | | 'mt--2'
36 | | 'mt-auto'
37 | | 'mb-0'
38 | | 'mb-1'
39 | | 'mb-2'
40 | | 'mb--1'
41 | | 'mb--2'
42 | | 'mb-auto'
43 | | 'ml-0'
44 | | 'ml-1'
45 | | 'ml-2'
46 | | 'ml--1'
47 | | 'ml--2'
48 | | 'ml-auto'
49 | | 'mr-0'
50 | | 'mr-1'
51 | | 'mr-2'
52 | | 'mr--1'
53 | | 'mr--2'
54 | | 'mr-auto'
55 | | 'm-0'
56 | | 'm-1'
57 | | 'm-2'
58 | | 'm-auto'
59 | | '';
60 |
61 | /* global inset rules */
62 | export type Inset =
63 | | 'py-0'
64 | | 'py-1'
65 | | 'py-2'
66 | | 'px-0'
67 | | 'px-1'
68 | | 'px-2'
69 | | 'pt-0'
70 | | 'pt-1'
71 | | 'pt-2'
72 | | 'pb-0'
73 | | 'pb-1'
74 | | 'pb-2'
75 | | 'pl-0'
76 | | 'pl-1'
77 | | 'pl-2'
78 | | 'pr-0'
79 | | 'pr-1'
80 | | 'pr-2'
81 | | 'p-0'
82 | | 'p-1'
83 | | 'p-2'
84 | | '';
85 |
--------------------------------------------------------------------------------
/src/lib/types/shape.d.ts:
--------------------------------------------------------------------------------
1 | /* class should be prefixed with `s-{type}` */
2 | export type Shape = 'none' | 'rounded' | 'circle';
3 |
--------------------------------------------------------------------------------
/src/lib/types/size.d.ts:
--------------------------------------------------------------------------------
1 | import type { SIZE, ZOOM } from './const';
2 |
3 | export type Size = keyof typeof SIZE;
4 | export type Zoom = keyof typeof ZOOM;
5 |
--------------------------------------------------------------------------------
/src/lib/types/text.d.ts:
--------------------------------------------------------------------------------
1 | /* class should be prefixed with `text-{type}` */
2 |
3 | export type Color =
4 | | 'initial'
5 | | 'primary'
6 | | 'secondary'
7 | | 'dark'
8 | | 'gray'
9 | | 'light'
10 | | 'success'
11 | | 'warning'
12 | | 'error'
13 | | '';
14 | export type Position = 'inherit' | 'left' | 'center' | 'right' | 'justify';
15 | export type Case = 'none' | 'lowercase' | 'uppercase' | 'capitalize';
16 | export type Weight =
17 | | 'normal'
18 | | 'bold'
19 | | 'italic'
20 | | 'muted'
21 | | 'large'
22 | | 'small'
23 | | 'tiny';
24 | export type Overflow = 'clip' | 'ellipsis' | 'break';
25 | export type Visibility = 'show' | 'hide' | 'assistive';
26 | export type Header = 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6';
27 |
--------------------------------------------------------------------------------
/src/www/+layout.server.ts:
--------------------------------------------------------------------------------
1 | export const prerender = true;
2 |
3 | const allMd = import.meta.glob('./**/*.md');
4 |
5 | let body = [];
6 |
7 | for (let path in allMd) {
8 | body.push(allMd[path]().then(({ metadata }) => ({ path, metadata })));
9 | }
10 |
11 | export async function load({ url }) {
12 | const mds = await Promise.all(body);
13 | const links = mds.reduce((accumulator: Links, current: Link) => {
14 | const key: string = current.path.split('/')[2];
15 | current.path = current.path.replace('+page.md', '');
16 | if (key.includes('.md')) return { ...accumulator, ['root']: [current] };
17 | return {
18 | ...accumulator,
19 | [key]: accumulator[key]
20 | ? [...accumulator[key], current]
21 | : [current],
22 | };
23 | }, {});
24 |
25 | const meta = getMeta(url.pathname) || null;
26 | const title = meta?.title;
27 |
28 | function getMeta(path: string) {
29 | const parts = path.split('/').filter(Boolean);
30 | const category = parts[1];
31 | const page = parts[2];
32 |
33 | return links[category]?.find((link: Link) => link.path.includes(page))
34 | .metadata;
35 | }
36 | return { links, meta, title };
37 | }
38 |
39 | interface Meta {
40 | file: string;
41 | title: string;
42 | config?: any;
43 | api?: Api[];
44 | }
45 |
46 | interface Api {
47 | title?: string;
48 | variables?: string;
49 | description?: string;
50 | }
51 |
52 | interface Link {
53 | metadata: Meta;
54 | path: string;
55 | }
56 | interface Links {
57 | [key: string]: Link[];
58 | }
59 |
--------------------------------------------------------------------------------
/src/www/+page.svelte:
--------------------------------------------------------------------------------
1 |
2 |
3 | {name}
4 |
5 | A Lightweight, Responsive and Modern UI-kit based on spectre.css
8 | and powered by Svelte and
9 | SvelteKit
12 |
13 |
14 | Docs
17 |
18 | GitHub
25 |
26 | Latest version: {version}
27 |
28 |
29 |
30 | Lightweight
31 | Lightweight (~10KB gzipped) starting point for your projects
32 |
33 |
34 |
35 |
36 | Responsive
37 | Flexbox-based, responsive and mobile-friendly layout
38 |
39 |
40 |
41 |
42 | Modern
43 | Elegantly designed and developed elements and components
44 |
45 |
46 |
47 |
48 | Get Started
53 |
54 | Components
57 |
58 | Layouts
59 |
60 |
61 |
62 |
63 |
68 |
69 |
73 |
74 |
90 |
--------------------------------------------------------------------------------
/src/www/app.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 | %sveltekit.head%
11 |
12 |
13 |
14 | %sveltekit.body%
15 |
16 |
17 |
--------------------------------------------------------------------------------
/src/www/app.scss:
--------------------------------------------------------------------------------
1 | @import 'assets/fonts/Exo2_64_Latin-ext.scss';
2 |
3 | html,
4 | body,
5 | .spectre {
6 | font-family: Exo2, sans-serif !important;
7 | font-size: 20px;
8 | margin: 0;
9 | }
10 |
11 | @media (max-width: 417px) {
12 | .basic_button_group a:nth-child(3) {
13 | margin-top: 20px !important;
14 | }
15 | }
16 |
17 | .clearText i{
18 | margin-left: 10px;
19 | margin-bottom: 4px;
20 | }
21 |
22 | .periodic_table_input dl{
23 | max-height: 400px;
24 | overflow-y: scroll;
25 | }
26 |
27 | .periodic_table_input .form-autocomplete-input{
28 | max-width: 600px!important;
29 | width: 600px!important
30 | }
31 |
32 | .form-switch.is-success .form-icon{
33 | border-color: green!important
34 | }
35 |
36 | .form-switch.is-success input:checked+.form-icon{
37 | background: green!important;
38 | border-color: green!important
39 | }
--------------------------------------------------------------------------------
/src/www/assets/.nojekyll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/basf/svelte-spectre/2ac9a9b34c504668d2227ddbb469d9c60898f7f4/src/www/assets/.nojekyll
--------------------------------------------------------------------------------
/src/www/assets/favicon.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/www/assets/github.svg:
--------------------------------------------------------------------------------
1 | GitHub
--------------------------------------------------------------------------------
/src/www/assets/img/04696e1a-eb5d-43b9-bb1d-d2ee117f4430.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/basf/svelte-spectre/2ac9a9b34c504668d2227ddbb469d9c60898f7f4/src/www/assets/img/04696e1a-eb5d-43b9-bb1d-d2ee117f4430.webp
--------------------------------------------------------------------------------
/src/www/assets/img/1b9a004a-db27-45e4-b762-0fa21bc97277.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/basf/svelte-spectre/2ac9a9b34c504668d2227ddbb469d9c60898f7f4/src/www/assets/img/1b9a004a-db27-45e4-b762-0fa21bc97277.webp
--------------------------------------------------------------------------------
/src/www/assets/img/4603a846-4daf-4018-aa74-e3ab567a69fc.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/basf/svelte-spectre/2ac9a9b34c504668d2227ddbb469d9c60898f7f4/src/www/assets/img/4603a846-4daf-4018-aa74-e3ab567a69fc.webp
--------------------------------------------------------------------------------
/src/www/assets/img/avatar-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/basf/svelte-spectre/2ac9a9b34c504668d2227ddbb469d9c60898f7f4/src/www/assets/img/avatar-1.png
--------------------------------------------------------------------------------
/src/www/assets/img/avatar-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/basf/svelte-spectre/2ac9a9b34c504668d2227ddbb469d9c60898f7f4/src/www/assets/img/avatar-2.png
--------------------------------------------------------------------------------
/src/www/assets/img/avatar-3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/basf/svelte-spectre/2ac9a9b34c504668d2227ddbb469d9c60898f7f4/src/www/assets/img/avatar-3.png
--------------------------------------------------------------------------------
/src/www/assets/img/avatar-4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/basf/svelte-spectre/2ac9a9b34c504668d2227ddbb469d9c60898f7f4/src/www/assets/img/avatar-4.png
--------------------------------------------------------------------------------
/src/www/assets/img/avatar-5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/basf/svelte-spectre/2ac9a9b34c504668d2227ddbb469d9c60898f7f4/src/www/assets/img/avatar-5.png
--------------------------------------------------------------------------------
/src/www/assets/img/b64f151d-e194-497a-9b70-e15ffdd8730d.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/basf/svelte-spectre/2ac9a9b34c504668d2227ddbb469d9c60898f7f4/src/www/assets/img/b64f151d-e194-497a-9b70-e15ffdd8730d.webp
--------------------------------------------------------------------------------
/src/www/assets/img/c2179403-954f-4f5d-82a4-3dfdeaba9597.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/basf/svelte-spectre/2ac9a9b34c504668d2227ddbb469d9c60898f7f4/src/www/assets/img/c2179403-954f-4f5d-82a4-3dfdeaba9597.webp
--------------------------------------------------------------------------------
/src/www/assets/metis.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/www/docs/+layout.svelte:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
8 |
9 |
22 |
--------------------------------------------------------------------------------
/src/www/docs/+page.svelte:
--------------------------------------------------------------------------------
1 |
2 | {name + '@' + version}: Getting started
3 |
4 |
5 | Getting started
6 |
7 |
8 | Spectre.css is a lightweight, responsive and modern CSS framework for faster and extensible
9 | development.
10 |
11 |
12 |
13 | Spectre provides basic styles for typography and elements, flexbox based responsive layout
14 | system, pure CSS components and utilities with best practice coding and consistent design
15 | language.
16 |
17 |
18 |
19 |
20 |
21 | Installation
22 | How to install and use Spectre.css
23 | View
28 |
29 |
30 |
31 |
32 | Customize
33 | Customize your version of Spectre.css
34 | View
39 |
40 |
41 |
42 |
43 | Browser support
44 | Browser compatibility and support
45 | View
50 |
51 |
52 |
53 |
54 | Changelog
55 | Changelog and release notes
56 | View
59 |
60 |
61 |
62 |
63 |
64 |
65 |
72 |
--------------------------------------------------------------------------------
/src/www/docs/01-getting_started/01-installation/+page.md:
--------------------------------------------------------------------------------
1 | ---
2 | file: installation.md
3 | title: Installation
4 | ---
5 |
6 |
9 |
10 | # {title}
11 |
12 | > ##### Requirements
13 | >
14 | > - `node -v >= 15`
15 | > - `npm -v >= 7`
16 |
17 | ## Installation
18 |
19 | ```bash
20 | npm install
21 | ```
22 |
23 | ## Building package
24 |
25 | ```bash
26 | # build components for GUI in package folder
27 | npm run package
28 | ```
29 |
30 | ## Developing
31 |
32 | ```bash
33 | npm run dev
34 |
35 | # or start the server and open the app in a new browser tab
36 | npm run dev -- --open
37 | ```
38 |
39 | ## Building
40 |
41 | Before creating a production version of your app, install an
42 | [adapter](https://kit.svelte.dev/docs#adapters) for your target environment.
43 | Then:
44 |
45 | ```bash
46 | npm run build
47 | ```
48 |
49 | You can preview the built app with `npm run preview`, regardless of whether you
50 | installed an adapter. This should _not_ be used to serve your app in production.
51 |
--------------------------------------------------------------------------------
/src/www/docs/01-getting_started/02-customize/+page.md:
--------------------------------------------------------------------------------
1 | ---
2 | file: customize.md
3 | title: Customize
4 | ---
5 |
6 |
9 |
10 | # {title}
11 |
12 | > 🚧 Under construction
13 |
14 | You can customize your version of Spectre.css by editing Sass files in /src
15 | directory or removing unneeded components from .scss source files.
16 |
--------------------------------------------------------------------------------
/src/www/docs/01-getting_started/browser-support/+page.md:
--------------------------------------------------------------------------------
1 | ---
2 | file: browser-support.md
3 | title: Browser support
4 | ---
5 |
6 |
9 |
10 | # {title}
11 |
12 | Spectre uses Autoprefixer to make most styles compatible with earlier browsers
13 | and Normalize.css for CSS resets. Spectre is designed for modern browsers. For
14 | best compatibility, these browsers are recommended:
15 |
16 | - Chrome LAST 4
17 | - Microsoft Edge LAST 4
18 | - Firefox Extended Support Release
19 | - Safari LAST 4
20 | - Opera LAST 4
21 | - Internet Explorer 10+
22 |
23 | Spectre supports Internet Explorer 10+, but some HTML5 and CSS3 features are not
24 | perfectly supported by Internet Explorer.
25 |
--------------------------------------------------------------------------------
/src/www/docs/01-getting_started/changelog/+page.md:
--------------------------------------------------------------------------------
1 | ---
2 | file: changelog.md
3 | title: Changelog
4 | ---
5 |
6 |
9 |
10 | # {title}
11 |
12 | > 🚧 Under construction
13 |
--------------------------------------------------------------------------------
/src/www/docs/components/breadcrumbs/+page.md:
--------------------------------------------------------------------------------
1 | ---
2 | file: breadcrumbs.md
3 | title: Breadcrumbs
4 | api:
5 | [
6 | {
7 | title: 'interface Link',
8 | description: 'interface Link',
9 | variables: 'interface Link {
10 | href: string;
11 | title: string;
12 | tooltip: string;
13 | }',
14 | },
15 | {
16 | title: 'href: string',
17 | description: 'Item link',
18 | variables: 'any URL string',
19 | },
20 | {
21 | title: 'title: string',
22 | description: 'Item title',
23 | variables: 'any string',
24 | },
25 | {
26 | title: 'title: tooltip',
27 | description: 'Item tooltip',
28 | variables: 'any string',
29 | },
30 | ]
31 | ---
32 |
33 |
42 |
43 | # {title}
44 |
45 | Breadcrumbs are used as navigational hierarchies to indicate current location.
46 |
47 |
48 |
49 |
50 |
51 | Add a container element with the `breadcrumb` class. And add child elements with
52 | the `breadcrumb-item` class.
53 |
54 | ```sv
55 |
64 |
65 |
66 | ```
67 |
--------------------------------------------------------------------------------
/src/www/docs/components/checkbox/+page.md:
--------------------------------------------------------------------------------
1 | ---
2 | file: checkbox.md
3 | title: Checkbox
4 | api:
5 | [
6 | {
7 | title: 'value: boolean = false',
8 | description: 'Checkbox value',
9 | variables: 'true | false',
10 | },
11 | {
12 | title: 'indeterminate: boolean = false',
13 | description: 'Checkbox indeterminate',
14 | variables: 'true | false',
15 | },
16 | {
17 | title: 'inline: boolean = false',
18 | description: 'Checkbox inline',
19 | variables: 'true | false',
20 | },
21 | {
22 | title: 'validity: Validity = null',
23 | description: 'Checkbox validity',
24 | variables: 'null | success | error',
25 | },
26 | ]
27 | config:
28 | {
29 | inline: { type: 'checkbox' },
30 | validity: { options: [null, 'success', 'error'] },
31 | indeterminate: { type: 'checkbox' },
32 | }
33 | ---
34 |
35 |
41 |
42 | # {title}
43 |
44 | You can change checkbox to indeterminate state by setting the indeterminate
45 | property of input checkboxes to true.
46 |
47 |
48 |
60 |
61 |
62 |
63 |
64 |
65 |
66 | ```sv
67 |
72 |
73 | Checkbox
74 | ```
75 |
--------------------------------------------------------------------------------
/src/www/docs/components/meter/+page.md:
--------------------------------------------------------------------------------
1 | ---
2 | file: meter.md
3 | title: Meter
4 | api:
5 | [
6 | {
7 | title: 'value: number = 0',
8 | description: 'Current numeric value',
9 | variables: 'any number',
10 | },
11 | {
12 | title: 'min: number = 0',
13 | description: 'The lower numeric bound of the measured range.',
14 | variables: 'any number',
15 | },
16 | {
17 | title: 'max: number = 100',
18 | description: 'The upper numeric bound of the measured range.',
19 | variables: 'any number',
20 | },
21 | {
22 | title: 'low: number = 26',
23 | description: 'The upper numeric bound of the low end of the measured range.',
24 | variables: 'any number',
25 | },
26 | {
27 | title: 'high: number = 51',
28 | description: 'The lower numeric bound of the high end of the measured range.',
29 | variables: 'any number',
30 | },
31 | {
32 | title: 'optimum: number = 90',
33 | description: 'This attribute indicates the optimal numeric value.',
34 | variables: 'any number',
35 | },
36 | {
37 | title: 'striped: boolean',
38 | description: 'Striped indicator.',
39 | variables: 'true | false',
40 | },
41 | {
42 | title: 'animated: boolean',
43 | description: 'Striped animated indicator.',
44 | variables: 'true | false',
45 | },
46 | {
47 | title: 'progress: boolean',
48 | description: 'Striped indicator like progress value',
49 | variables: 'true | false',
50 | },
51 | ]
52 | config:
53 | {
54 | striped: { type: 'checkbox' },
55 | animated: { type: 'checkbox' },
56 | progress: { type: 'checkbox' },
57 | value: { type: 'number', min: 0, max: 100, size: 5 },
58 | min: { type: 'number', min: 0, max: 100, size: 5 },
59 | max: { type: 'number', min: 0, max: 100, size: 5 },
60 | low: { type: 'number', min: 0, max: 100, size: 5 },
61 | high: { type: 'number', min: 0, max: 100, size: 5 },
62 | optimum: { type: 'number', min: 0, max: 100, size: 5 },
63 | }
64 | ---
65 |
66 |
82 |
83 | # {title}
84 |
85 | Meters represent the value within the known range.
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 | ```sv
96 |
110 |
111 |
112 | ```
113 |
--------------------------------------------------------------------------------
/src/www/docs/components/pagination/+page.md:
--------------------------------------------------------------------------------
1 | ---
2 | file: pagination.md
3 | title: Pagination
4 | api: [
5 | {title: 'page: number', description: 'Active page number', variables: 'any number'},
6 | {title: 'total: number', description: 'Total items', variables: 'any number'},
7 | {title: 'limit: number', description: 'Limit items per page', variables: 'any number'},
8 | {title: 'rest: number', description: 'Links to pages to be shown', variables: 'any number'},
9 | {title: 'perpage: boolean', description: 'Select limit per page', variables: 'true | false'},
10 | ]
11 | config:
12 | {
13 | page: { type: 'number', size: 10, min: 1, max: 150 },
14 | total: { type: 'number', size: 10, min: 10, max: 1500 },
15 | limit: { type: 'number', size: 10, min: 10, max: 100, step: 10 },
16 | rest: { type: 'number', size: 10, min: 0, max: 10 },
17 | perpage: { type: 'checkbox' }
18 | }
19 | ---
20 |
21 |
33 |
34 | # {title}
35 |
36 | Add a container element with the pagination class. And add child elements with
37 | the page-item class. The page-item with the active class will be highlighted.
38 | You can add the disabled class to the page-item to have unclickable page links.
39 |
40 |
41 |
47 |
48 |
49 |
50 |
51 |
52 |
53 | ```sv
54 |
58 |
59 |
60 | ```
61 |
--------------------------------------------------------------------------------
/src/www/docs/components/periodictable/+page.md:
--------------------------------------------------------------------------------
1 | ---
2 | file: periodictable.md
3 | title: Periodic Table
4 | api: [
5 | {title: 'selected: string[] = []', description: 'Selected element array output', variables: '["H", "He", "Li", "Be", "B", "C", "N", "O", "F", "Ne", "Na", "Mg", "Al", "Si", "P", "S", "Cl", "Ar", "K", "Ca", "Sc", "Ti", "V", "Cr", "Mn", "Fe", "Co", "Ni", "Cu", "Zn", "Ga", "Ge", "As", "Se", "Br", "Kr", "Rb", "Sr", "Y", "Zr", "Nb", "Mo", "Tc", "Ru", "Rh", "Pd", "Ag", "Cd", "In", "Sn", "Sb", "Te", "I", "Xe", "Cs", "Ba", "La", "Ce", "Pr", "Nd", "Pm", "Sm", "Eu", "Gd", "Tb", "Dy", "Ho", "Er", "Tm", "Yb", "Lu", "Hf", "Ta", "W", "Re", "Os", "Ir", "Pt", "Au", "Hg", "Tl", "Pb", "Bi", "Po", "At", "Rn", "Fr", "Ra", "Ac", "Th", "Pa", "U", "Np", "Pu", "Am", "Cm", "Bk", "Cf", "Es", "Fm", "Md", "No","period 1", "period 2", "period 3", "period 4", "period 5", "period 6", "period 7", "lanthanide", "actinide", "alkali", "alkaline", "group 3", "group 4", "group 5", "group 6", "group 7", "group 8", "group 9", "group 10", "group 11", "group 12", "triels", "tetrels", "pnictogen", "chalcogen", "halogen", "noble gas"]'},
6 | {title: 'clear: function()', description: 'Clear selection', variables: ''}
7 | ]
8 | config: {}
9 | ---
10 |
11 |
35 |
36 | # {title}
37 |
38 | The Periodic Table component allows to select chemical elements conveniently. Currently up to 3 distinct chemical elements or up to 3 named groups can be selected. A named group is either a column or a row in the periodic table, such as `alkali`, `alkalines`, `pnictogens`, `chalcogens`, `period 2`, `period 6`, `lanthanides`, `actinides`, etc.
39 |
40 | open = !open}>Open Periodic Table
41 |
42 |
43 |
44 |
45 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
64 |
65 | ```sv
66 |
71 |
72 |
73 | ```
74 |
--------------------------------------------------------------------------------
/src/www/docs/components/progress/+page.md:
--------------------------------------------------------------------------------
1 | ---
2 | file: progress.md
3 | title: Progress
4 | api: [
5 | {title: 'value: number = undefined', description: 'Progress value', variables: 'any number'},
6 | {title: 'max: number = 0', description: 'Progress max', variables: 'any number'},
7 | {title: 'color: Colors = "light"', description: 'Progress color', variables: 'gray | light | primary | secondary | success | error'},
8 | {title: 'invert: boolean = false', description: 'Progress invert', variables: 'true | false'}
9 | ]
10 | config: {
11 | value: { type: 'number', min: 0, max: 100, size: 5 },
12 | max: { type: 'number', min: 0, max: 100, size: 5 },
13 | color: { options: [ 'gray', 'light', 'primary', 'secondary', 'success', 'error' ] } ,
14 | invert: { type: 'checkbox'}
15 | }
16 | ---
17 |
18 |
24 |
25 | # {title}
26 |
27 | The Progress indicates the progress completion of a task.
28 |
29 | > If `value === null || undefined` it have indeterminate/loading state
30 |
31 |
32 |
33 |
34 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 | ```sv
57 |
60 |
61 |
62 |
63 |
64 |
65 | ```
66 |
--------------------------------------------------------------------------------
/src/www/docs/components/radio/+page.md:
--------------------------------------------------------------------------------
1 | ---
2 | file: radio.md
3 | title: Radio
4 | api:
5 | [
6 | {
7 | title: '',
8 | description: 'Radio item from array',
9 | variables: '{radio.some} ',
10 | },
11 | {
12 | title: 'radios: any[] = []',
13 | description: 'Radio items array',
14 | variables: 'any array',
15 | },
16 | {
17 | title: 'label: string = ""',
18 | description: 'Radio label',
19 | variables: 'any string',
20 | },
21 | {
22 | title: 'group: number = 0',
23 | description: 'Radio selected index',
24 | variables: 'any number',
25 | },
26 | {
27 | title: 'inline: boolean = false',
28 | description: 'Checkbox inline',
29 | variables: 'true | false',
30 | },
31 | {
32 | title: 'validity: Validity = null',
33 | description: 'Checkbox validity',
34 | variables: 'null | success | error',
35 | },
36 | ]
37 | config:
38 | {
39 | label: { size: 12 },
40 | group: { type: 'number', min: 0, max: 2, size: 5 },
41 | inline: { type: 'checkbox' },
42 | validity: { options: [null, 'success', 'error'] },
43 | }
44 | ---
45 |
46 |
58 |
59 | # {title}
60 |
61 |
62 |
76 | Selected: {state.group}
77 |
78 |
79 |
80 |
81 |
82 |
83 | ```sv
84 |
89 |
90 |
97 | {radio.label}
98 |
99 | ```
100 |
--------------------------------------------------------------------------------
/src/www/docs/components/range/+page.md:
--------------------------------------------------------------------------------
1 | ---
2 | file: range.md
3 | title: Range
4 | api:
5 | [
6 | {
7 | title: 'range: number = 50',
8 | description: 'Checkbox range',
9 | variables: 'any number',
10 | },
11 | {
12 | title: 'min: number = 0',
13 | description: 'Checkbox range',
14 | variables: 'any number',
15 | },
16 | {
17 | title: 'max: number = 100',
18 | description: 'Checkbox range',
19 | variables: 'any number',
20 | },
21 | {
22 | title: 'inline: boolean = false',
23 | description: 'Checkbox range',
24 | variables: 'true | false',
25 | },
26 | {
27 | title: 'validity: Validity = null',
28 | description: 'Checkbox validity',
29 | variables: 'null | success | error',
30 | },
31 | ]
32 | config:
33 | {
34 | range: { type: 'number', min: 0, max: 100, size: 10 },
35 | min: { type: 'number', min: 0, max: 10, size: 10 },
36 | max: { type: 'number', min: 10, max: 100, size: 10 },
37 | inline: { type: 'checkbox' },
38 | validity: { options: [null, 'success', 'error'] },
39 | }
40 | ---
41 |
42 |
48 |
49 | # {title}
50 |
51 | The Range are for selecting values from ranges.
52 |
53 |
54 |
65 |
66 |
67 |
68 |
69 |
70 |
71 | ```sv
72 |
77 |
78 |
84 | ```
85 |
--------------------------------------------------------------------------------
/src/www/docs/components/steps/+page.md:
--------------------------------------------------------------------------------
1 | ---
2 | file: steps.md
3 | title: Steps
4 | api:
5 | [
6 | {
7 | title: 'steps: Step[] = []',
8 | description: 'interface Step',
9 | variables: 'interface Step {
10 | label: string;
11 | href?: string;
12 | tooltip?: string;
13 | }',
14 | },
15 | {
16 | title: 'Step.label: string = ""',
17 | description: 'Step label',
18 | variables: 'any string',
19 | },
20 | {
21 | title: 'Step.gref: string = ""',
22 | description: 'Step href',
23 | variables: 'any url string',
24 | },
25 | {
26 | title: 'Step.tooltip: string = ""',
27 | description: 'Step tooltip',
28 | variables: 'any string',
29 | },
30 | {
31 | title: 'active: number = 1',
32 | description: 'Active step',
33 | variables: 'any number',
34 | },
35 | ]
36 | config:
37 | {
38 | active: { type: 'number', min: 1, max: 10, size: 5 },
39 | length: { type: 'number', min: 2, max: 10, size: 5 },
40 | }
41 | ---
42 |
43 |
53 |
54 | # {title}
55 |
56 | Steps are progress indicators of a sequence of task steps.
57 |
58 | Add a container element with the step class. And add child elements with the
59 | step-item class. The step-item with the active class will be highlighted and
60 | indicate the current state of progress.
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 | ```sv
71 |
83 |
84 |
85 | ```
86 |
--------------------------------------------------------------------------------
/src/www/docs/components/switch/+page.md:
--------------------------------------------------------------------------------
1 | ---
2 | file: switch.md
3 | title: Switch
4 | api:
5 | [
6 | {
7 | title: 'value: boolean = false',
8 | description: 'Checkbox value',
9 | variables: 'true | false',
10 | },
11 | {
12 | title: 'inline: boolean = false',
13 | description: 'Checkbox inline',
14 | variables: 'true | false',
15 | },
16 | {
17 | title: 'validity: Validity = null',
18 | description: 'Checkbox validity',
19 | variables: 'null | success | error',
20 | },
21 | ]
22 | config:
23 | {
24 | inline: { type: 'checkbox' },
25 | validity: { options: [null, 'success', 'error'] },
26 | }
27 | ---
28 |
29 |
35 |
36 | # {title}
37 |
38 | The form switch element is an important component that is required to get the activation value or on/off value from the user:
39 |
40 |
41 |
51 |
52 |
53 |
54 |
55 |
56 |
57 | ```sv
58 |
63 |
64 | Switch
65 | ```
66 |
--------------------------------------------------------------------------------
/src/www/docs/components/transition/+page.md:
--------------------------------------------------------------------------------
1 | ---
2 | file: transition.md
3 | title: Transition
4 | ---
5 |
6 |
9 |
10 | # {title}
11 |
12 | > 🚧 Under construction
13 |
--------------------------------------------------------------------------------
/src/www/docs/layouts/card/+page.md:
--------------------------------------------------------------------------------
1 | ---
2 | file: card.md
3 | title: Card
4 | api: [
5 | {title: 'pos: Position = "center"', description: 'Image Posistion', variables: 'center | top | bottom'},
6 | {title: ': HTMLelement | SvelteComponent', description: 'image in Card', variables: 'HTMLelement | SvelteComponent'},
7 | {title: ': HTMLelement | SvelteComponent', description: 'Card title or header', variables: 'HTMLelement | SvelteComponent'},
8 | {title: ': HTMLelement | SvelteComponent', description: 'Card subtitle', variables: 'HTMLelement | SvelteComponent'},
9 | {title: ': HTMLelement | SvelteComponent', description: 'Card footer', variables: 'HTMLelement | SvelteComponent'}
10 | ]
11 | ---
12 |
13 |
50 |
51 | # {title}
52 |
53 | Cards are flexible content containers. Add child elements with the image, title, subtitle, content and/or footer slot. The image can be placed in any position:
54 |
55 | ```sv
56 |
65 |
66 |
67 |
68 | {title}
69 | {subTitle}
70 | {text}
71 |
72 | Primary
73 | Link
74 |
75 |
76 | ```
77 |
78 |
79 |
80 | {#each CARDS as { col, pos, img, text }}
81 |
82 |
83 |
84 | Title
85 | SubTitle
86 | {text}
87 |
88 | Primary
89 | Link
90 |
91 |
92 |
93 | {/each}
94 |
95 |
96 |
--------------------------------------------------------------------------------
/src/www/docs/layouts/code/+page.md:
--------------------------------------------------------------------------------
1 | ---
2 | file: code.md
3 | title: Code
4 | api: [
5 | {title: 'lang: String', description: 'Set program language', variables: 'js | php | go | rust | python ...'},
6 | ]
7 | ---
8 |
9 |
12 |
13 | # {title}
14 |
15 | Code is a flexible container. It is used for styling inline and multiline code snippets.
16 |
17 | ```sv
18 | import { Code } from 'svelte-spectre'
19 |
20 |
21 |
22 |
23 | let binding = Function.prototype.call.bind(Function.prototype.bind);
24 |
25 |
26 | ```
27 |
28 |
29 |
30 | let binding = Function.prototype.call.bind(Function.prototype.bind);
31 |
32 |
33 |
--------------------------------------------------------------------------------
/src/www/docs/layouts/container/+page.md:
--------------------------------------------------------------------------------
1 | ---
2 | file: container.md
3 | title: Container
4 | api: [
5 | {title: 'size: Size = "md"', description: 'Container width', variables: 'lg | md | sm | xs'}
6 | ]
7 | ---
8 |
9 |
13 |
14 | # {title}
15 |
16 | Container contains further components or elements.
17 |
18 | ```sv
19 |
23 |
24 |
25 |
26 | Computer, show me periodic table!
27 |
28 |
29 | ```
30 |
31 |
32 |
33 |
34 | Computer, show me periodic table!
35 |
36 |
37 |
--------------------------------------------------------------------------------
/src/www/docs/layouts/empty/+page.md:
--------------------------------------------------------------------------------
1 | ---
2 | file: empty.md
3 | title: Empty
4 | api: [
5 | {title: ': HTMLelement | SvelteComponent', description: 'Icon in Empty', variables: 'HTMLelement | SvelteComponent'},
6 | {title: ': HTMLelement | SvelteComponent', description: 'Empty title or header', variables: 'HTMLelement | SvelteComponent'},
7 | {title: ': HTMLelement | SvelteComponent', description: 'Empty subtitle', variables: 'HTMLelement | SvelteComponent'},
8 | {title: ': HTMLelement | SvelteComponent', description: 'Empty footer', variables: 'HTMLelement | SvelteComponent'}
9 | ]
10 | ---
11 |
12 |
15 |
16 | # {title}
17 |
18 | Empty states/blank slates are commonly used as placeholders for first time use, empty data and error screens.
19 |
20 | ```sv
21 |
24 |
25 |
26 |
27 | Title
28 | Subtitle
29 | Action
30 |
31 | ```
32 |
33 |
34 |
35 | Title
36 | Subtitle
37 | Action
38 |
39 |
--------------------------------------------------------------------------------
/src/www/docs/layouts/figure/+page.md:
--------------------------------------------------------------------------------
1 | ---
2 | file: figure.md
3 | title: Figure
4 | api: [
5 | {title: 'contain: Boolean', description: 'Image size(img-fit-contain)', variables: ' true | false'},
6 | {title: 'cover: Boolean', description: 'Image size(img-fit-cover)', variables: ' true | false'},
7 | {title: 'align: Align = "left"', description: 'Text position', variables: ' left | center | right'}
8 | ]
9 | ---
10 |
11 |
15 |
16 | # {title}
17 |
18 | You can use the element `` for an image with a caption. You can also add `contain, cover = true | false`, `align = left | center | right`
19 |
20 | ```sv
21 |
24 |
25 |
30 | img-fit-cover
31 |
32 | ```
33 |
34 |
35 |
36 |
37 |
38 |
39 | img-fit-contain
44 |
45 |
46 | img-fit-cover
51 |
52 |
53 |
--------------------------------------------------------------------------------
/src/www/docs/layouts/form/+page.md:
--------------------------------------------------------------------------------
1 | ---
2 | file: form.md
3 | title: Form
4 | api: [
5 | {title: 'horizontal: Boolean', description: 'component horizon', variables: ' true | false'},
6 | {title: 'validity: Validity', description: 'component validator', variables: ' success | error'},
7 |
8 | ]
9 | ---
10 |
11 |
14 |
15 | # {title}
16 |
17 | Form provides the most common controls, including input, textarea, select, checkbox, radio, and switch, as well as their groups.
18 |
19 | ```sv
20 |
23 |
24 |
36 | ```
37 |
38 |
50 |
--------------------------------------------------------------------------------
/src/www/docs/layouts/grid/+page.md:
--------------------------------------------------------------------------------
1 | ---
2 | file: grid.md
3 | title: Grid
4 | api:
5 | [
6 | {
7 | title: 'gapless: Boolean',
8 | description: 'Provide gapless component',
9 | variables: 'true | false',
10 | },
11 | {
12 | title: 'oneline: Boolean',
13 | description: 'Provide oneline component',
14 | variables: 'true | false',
15 | },
16 | {
17 | title: 'stack: Boolean',
18 | description: 'Provide stacked component',
19 | variables: ' true | false',
20 | },
21 | {
22 | title: 'align: Align',
23 | description: 'component position',
24 | variables: ' start | center | end | stretch | ""',
25 | },
26 | {
27 | title: 'justify: Justify',
28 | description: 'component position',
29 | variables: ' start | center | end | stretch | ""',
30 | },
31 | ]
32 | ---
33 |
34 |
38 |
39 | # {title}
40 |
41 | Layout includes flexbox-based responsive grid system with 12 columns. You can specify the width of each column by adding attribute `col=<1-12>`
42 |
43 | ```sv
44 |
47 |
48 |
49 | col-5
50 | col-7
51 | col-8
52 | col-4
53 |
54 | ```
55 |
56 |
57 | col-5
58 | col-7
59 | col-8
60 | col-4
61 | col
62 |
63 |
--------------------------------------------------------------------------------
/src/www/docs/layouts/hero/+page.md:
--------------------------------------------------------------------------------
1 | ---
2 | file: hero.md
3 | title: Hero
4 | api: [
5 | {title: 'size: Size', description: 'component size', variables: 'xs | sm | md | lg | xl | xxl'},
6 | {title: 'bg: Color', description: 'background color', variables: 'initial | primary | secondary | dark | darked | gray | light | success | warning | error'},
7 | {title: 'center: Boolean', description: 'text center', variables: 'true | false'},
8 | ]
9 | ---
10 |
11 |
15 |
16 | # {title}
17 |
18 | The Hero container shows key featured content or important information.
19 |
20 | ```sv
21 |
24 |
25 |
26 | ```
27 |
28 |
29 |
--------------------------------------------------------------------------------
/src/www/docs/layouts/navbar/+page.md:
--------------------------------------------------------------------------------
1 | ---
2 | file: navbar.md
3 | title: Navbar
4 | api: [
5 | {title: ': HTMLelement | SvelteComponent', description: 'left component in navbar', variables: 'HTMLelement | SvelteComponent'},
6 | {title: ': HTMLelement | SvelteComponent', description: 'center component in navbar', variables: 'HTMLelement | SvelteComponent'},
7 | {title: ': HTMLelement | SvelteComponent', description: 'right component in navbar', variables: 'HTMLelement | SvelteComponent'},
8 | ]
9 | ---
10 |
11 |
15 |
16 | # {title}
17 |
18 | Navbar is the layout container that normally appears in the header of the apps and websites.
19 |
20 | ```sv
21 |
24 |
25 |
26 |
27 |
28 |
29 |
30 | ```
31 |
32 |
39 |
--------------------------------------------------------------------------------
/src/www/docs/layouts/panel/+page.md:
--------------------------------------------------------------------------------
1 | ---
2 | file: panel.md
3 | title: Panel
4 | api: [
5 | {title: ': HTMLelement | SvelteComponent', description: 'Header in Panel', variables: 'HTMLelement | SvelteComponent'},
6 | {title: ': HTMLelement | SvelteComponent', description: 'Nav in Panel', variables: 'HTMLelement | SvelteComponent'},
7 | {title: ': HTMLelement | SvelteComponent', description: 'Body in Panel', variables: 'HTMLelement | SvelteComponent'},
8 | {title: ': HTMLelement | SvelteComponent', description: 'Footer in Panel', variables: 'HTMLelement | SvelteComponent'}
9 | ]
10 | ---
11 |
12 |
15 |
16 | # {title}
17 |
18 | Panel is a flexible view container with an auto-expand content section. Panel is similar to the card component with more flexibility. For example, it can be used to create a conversation layout.
19 |
20 | ```sv
21 |
24 |
25 |
26 |
27 |
28 | Svelte-Spectre
29 |
30 |
31 | About
32 |
33 |
34 | A Lightweight, Responsive and Modern UI-kit based on spectre.css and powered by Svelte and SvelteKit
35 |
36 |
37 | © 2022 — 2023 BASF SE
38 |
39 |
40 |
41 | ```
42 |
43 |
44 |
45 |
46 | Svelte-Spectre
47 |
48 |
49 | About
50 |
51 |
52 | A Lightweight, Responsive and Modern UI-kit based on spectre.css and powered by Svelte and SvelteKit
53 |
54 |
55 | © 2022 — 2023 BASF SE
56 |
57 |
58 |
--------------------------------------------------------------------------------
/src/www/docs/layouts/sidebar/+page.md:
--------------------------------------------------------------------------------
1 | ---
2 | file: sidebar.md
3 | title: Sidebar
4 | ---
5 |
6 |
9 |
10 | # {title}
11 |
12 | The `Sidebar` is a navigation layout that the sidebar can slide in and out of
13 | the viewport. It is built in pure CSS.
14 |
15 | By default, the Sidebar is collapsed whenever the window width is. But you can
16 | add the `off-canvas-sidebar-show` class to the `off-canvas` to make the sidebar
17 | expanded when the window width is larger than or equal to 960px.
18 |
--------------------------------------------------------------------------------
/src/www/docs/layouts/tile/+page.md:
--------------------------------------------------------------------------------
1 | ---
2 | file: tile.md
3 | title: Tile
4 | api: [
5 | {title: 'centered: Boolean', description: 'set component in center', variables: 'true | false'},
6 | {title: ': HTMLelement | SvelteComponent', description: 'image or icon in tile', variables: 'HTMLelement | SvelteComponent'},
7 | {title: ': HTMLelement | SvelteComponent', description: 'title text in tile', variables: 'HTMLelement | SvelteComponent'},
8 | {title: ': HTMLelement | SvelteComponent', description: 'subtitle text in tile', variables: 'HTMLelement | SvelteComponent'},
9 | {title: ': HTMLelement | SvelteComponent', description: 'action component in tile', variables: 'HTMLelement | SvelteComponent'},
10 | ]
11 | ---
12 |
13 |
16 |
17 | # {title}
18 |
19 | Tiles are repeatable or embeddable information blocks.
20 |
21 | ```sv
22 |
25 |
26 |
27 |
28 |
29 |
30 |
31 | The Avengers
32 | Earth's Mightiest Heroes joined forces to take on threats that were too big for any one hero to tackle...
33 |
34 | Join
35 |
36 |
37 |
38 | ```
39 |
40 |
41 |
42 |
43 |
44 |
45 | The Avengers
46 | Earth's Mightiest Heroes joined forces to take on threats that were too big for any one hero to tackle...
47 |
48 | Join
49 |
50 |
51 |
52 |
--------------------------------------------------------------------------------
/src/www/docs/layouts/toggle/+page.md:
--------------------------------------------------------------------------------
1 | ---
2 | file: toggle.md
3 | title: Toggle
4 | api:
5 | [
6 | {
7 | title: ': HTMLElement | SvelteComponent',
8 | description: 'Toggle toggler',
9 | variables: 'HTMLElement | SvelteComponent',
10 | },
11 | {
12 | title: ': HTMLElement | SvelteComponent',
13 | description: 'Toggle content',
14 | variables: 'HTMLElement | SvelteComponent',
15 | },
16 | {
17 | title: 'toggle: boolean = false',
18 | description: 'Toggle toggle state',
19 | variables: 'true | false',
20 | },
21 | ]
22 | config: { toggle: { type: 'checkbox' } }
23 | ---
24 |
25 |
32 |
33 | # {title}
34 |
35 | Toggle is a flexible wrapper which provides just the slots for the content.
36 | You can control it with the `toggle: boolean` flag.
37 |
38 |
39 |
40 |
41 | (state.toggle = !state.toggle)}>
44 | {state.toggle ? 'Hide content' : 'Show content'}
45 |
46 |
47 |
48 | Toggled content
49 | This is the toggled content.
50 | (state.toggle = false)}>
52 | Hide toggled content
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 | ```sv
62 |
68 |
69 |
70 | toggle = !toggle}>
71 | {toggle ? 'Hide' : 'Show'}
72 |
73 |
74 | Toggled header
75 | Toggled content
76 |
77 |
78 | ```
79 |
--------------------------------------------------------------------------------
/src/www/media.ts:
--------------------------------------------------------------------------------
1 | import { type Readable, readable } from 'svelte/store';
2 |
3 | export type Queries = {
4 | [key: string]: boolean | string;
5 | };
6 |
7 | type MediaObject = {
8 | [key: string]: MediaQueryList;
9 | };
10 |
11 | const queries: Queries = {
12 | xs: '(max-width: 480px)',
13 | sm: '(max-width: 600px)',
14 | md: '(max-width: 840px)',
15 | lg: '(max-width: 960px)',
16 | xl: '(max-width: 1280px)',
17 | xxl: '(min-width: 1281px)',
18 | landscape: '(orientation: landscape)',
19 | portrait: '(orientation: portrait)',
20 | dark: '(prefers-color-scheme: dark)',
21 | light: '(prefers-color-scheme: light)',
22 | mouse: '(hover: hover)',
23 | touch: '(hover: none)',
24 | };
25 |
26 | export const media: Readable = mediaStore(queries);
27 |
28 | function mediaStore(queries: Queries = {}) {
29 | return readable({}, (set) => {
30 | let mqs = Object.entries(queries).reduce(
31 | (mqs: MediaObject, [key, query]) => {
32 | if (typeof window === 'object') {
33 | mqs[key] = matchMedia(query as string);
34 | mqs[key].onchange = (mq) => {
35 | mqs[key] = mq;
36 | update();
37 | };
38 | }
39 | return mqs as MediaObject;
40 | },
41 | {}
42 | );
43 |
44 | function update() {
45 | const matches: Queries = Object.entries(mqs).reduce(
46 | (matches: Queries, [key, mq]) => {
47 | matches[key] = mq.matches;
48 | return matches;
49 | },
50 | {}
51 | );
52 | set(matches);
53 | }
54 |
55 | update();
56 |
57 | return () => (mqs = {});
58 | });
59 | }
60 |
--------------------------------------------------------------------------------
/src/www/types.ts:
--------------------------------------------------------------------------------
1 | interface Meta {
2 | file: string;
3 | title: string;
4 | config?: any;
5 | api?: Api[];
6 | }
7 |
8 | type Api = {
9 | title?: string;
10 | variables?: string;
11 | description?: string;
12 | };
13 |
14 | type Link = {
15 | metadata: Meta;
16 | path: string;
17 | };
18 |
19 | interface Links {
20 | [key: string]: Link[];
21 | }
22 |
23 | export interface Data {
24 | links: Links;
25 | meta: Meta;
26 | title: string;
27 | }
28 |
--------------------------------------------------------------------------------
/svelte.config.js:
--------------------------------------------------------------------------------
1 | import { mdsvex } from 'mdsvex';
2 | import preprocess from 'svelte-preprocess';
3 | import mdsvexConfig from './mdsvex.config.js';
4 | import adapterStatic from '@sveltejs/adapter-static';
5 |
6 | const env = (type) => process.env.npm_lifecycle_event === type;
7 |
8 | const primaryColor = env('package') ? '' : '$primary-color: hsl(215, 15%, 33%);';
9 |
10 | const options = {
11 | sourceMap: env('dev'),
12 | scss: {
13 | prependData: `
14 | ${primaryColor}
15 | @import './node_modules/spectre.css/src/variables';
16 | @import './node_modules/spectre.css/src/mixins';
17 | @import './src/lib/dark';
18 | `,
19 | quietDeps: true,
20 | renderSync: true,
21 | },
22 | typescript: true,
23 | };
24 |
25 | /** @type {import('@sveltejs/kit').Config} */
26 | export default {
27 | // https://github.com/sveltejs/svelte-preprocess
28 | compilerOptions: { immutable: false },
29 | preprocess: [preprocess(options), mdsvex(mdsvexConfig)],
30 | extensions: ['.svelte', ...mdsvexConfig.extensions],
31 |
32 | onwarn: (warning, handler) => {
33 | const ignore = [
34 | 'a11y-invalid-attribute',
35 | 'a11y-label-has-associated-control',
36 | 'a11y-missing-content',
37 | 'a11y-structure',
38 | 'a11y-autofocus',
39 | 'css-unused-selector',
40 | 'missing-declaration',
41 | 'unused-export-let',
42 | ];
43 | if (ignore.includes(warning.code)) return;
44 | console.log('w:', warning);
45 | handler(warning);
46 | },
47 |
48 | kit: {
49 | adapter: adapterStatic(),
50 | files: {
51 | assets: 'src/www/assets',
52 | routes: 'src/www',
53 | appTemplate: 'src/www/app.html',
54 | },
55 | prerender: {
56 | handleMissingId: 'warn',
57 | },
58 | },
59 | package: {
60 | dir: 'package',
61 | emitTypes: true,
62 | },
63 | };
64 |
--------------------------------------------------------------------------------
/tests/components/Accordion/Accordion.spec.ts:
--------------------------------------------------------------------------------
1 | import { test } from 'uvu';
2 | import * as assert from 'uvu/assert';
3 | import * as ENV from '../../setup/testenv';
4 |
5 | import Accordion from '../../../src/lib/components/Accordion';
6 |
7 | test.before(ENV.setup);
8 | test.before.each(ENV.reset);
9 |
10 | test('check Accordion', async () => {
11 | const { container, component } = ENV.render(Accordion, {
12 | title: 'Accordion',
13 | });
14 | const accordion: HTMLElement = container.querySelector('.accordion');
15 | const summary: HTMLElement = container.querySelector('.accordion-header');
16 | await ENV.fire(summary, 'click');
17 | accordion.querySelector('.accordion-body').innerHTML = 'accordion-body';
18 |
19 | assert.is(accordion.innerHTML.includes(`accordion-body`), true);
20 | // assert.snapshot(container.innerHTML, 'just render view');
21 | });
22 |
23 | test.run();
24 |
--------------------------------------------------------------------------------
/tests/components/Avatar/Avatar.spec.ts:
--------------------------------------------------------------------------------
1 | import { test } from 'uvu';
2 | import * as assert from 'uvu/assert';
3 | import * as ENV from '../../setup/testenv';
4 |
5 | import Avatar from '../../../src/lib/components/Avatar';
6 |
7 | test.before(ENV.setup);
8 | test.before.each(ENV.reset);
9 |
10 | test('check Avatar', async () => {
11 | const { container, component } = ENV.render(Avatar, { title: 'Accordion' });
12 | const avatar: HTMLElement = container.querySelector('.avatar');
13 | avatar.innerHTML = 'avatar';
14 |
15 | assert.is(avatar.innerHTML.includes(`avatar`), true);
16 | // assert.snapshot(container.innerHTML, 'just render view');
17 | });
18 |
19 | test.run();
20 |
--------------------------------------------------------------------------------
/tests/components/Badge/Badge.spec.ts:
--------------------------------------------------------------------------------
1 | import { test } from 'uvu';
2 | import * as assert from 'uvu/assert';
3 | import * as ENV from '../../setup/testenv';
4 |
5 | import Badge from '../../../src/lib/components/Badge';
6 |
7 | test.before(ENV.setup);
8 | test.before.each(ENV.reset);
9 |
10 | test('check Badge', async () => {
11 | const { container, component } = ENV.render(Badge, {
12 | color: 'primary',
13 | rounded: true,
14 | });
15 | const badge: HTMLElement = container.querySelector('.label');
16 | badge.innerHTML = 'badge';
17 |
18 | assert.is(badge.innerHTML.includes(`badge`), true);
19 | assert.is(badge.classList.contains(`label-primary`), true);
20 | assert.is(badge.classList.contains(`label-rounded`), true);
21 | // assert.snapshot(container.innerHTML, 'just render view');
22 | });
23 |
24 | test.run();
25 |
--------------------------------------------------------------------------------
/tests/components/Breadcrumbs/Breadcrumbs.spec.ts:
--------------------------------------------------------------------------------
1 | import { test } from 'uvu';
2 | import * as assert from 'uvu/assert';
3 | import * as ENV from '../../setup/testenv';
4 |
5 | import Breadcrumbs from '../../../src/lib/components/Breadcrumbs';
6 |
7 | const links = [
8 | { title: '1', href: '#' },
9 | { title: '2', href: '#' },
10 | { title: '3', href: '#' },
11 | ];
12 |
13 | test.before(ENV.setup);
14 | test.before.each(ENV.reset);
15 |
16 | test('check Breadcrumbs', async () => {
17 | const { container, component } = ENV.render(Breadcrumbs, { links });
18 | const breadcrumb: HTMLElement = container.querySelector('.breadcrumb');
19 |
20 | assert.is(breadcrumb.querySelectorAll(`.breadcrumb-item`).length, 3);
21 | // assert.snapshot(container.innerHTML, 'just render view');
22 | });
23 |
24 | test.run();
25 |
--------------------------------------------------------------------------------
/tests/components/Button/Button.spec.ts:
--------------------------------------------------------------------------------
1 | import { test } from 'uvu';
2 | import * as assert from 'uvu/assert';
3 | import * as ENV from '../../setup/testenv';
4 |
5 | import Button from '../../../src/lib/components/Button/Button.svelte';
6 |
7 | test.before(ENV.setup);
8 | test.before.each(ENV.reset);
9 |
10 | test('check button variants', () => {
11 | const { container } = ENV.render(Button, { variant: 'primary' });
12 | const button = container.querySelector('button');
13 | assert.is(button.classList.contains(`btn-primary`), true);
14 | });
15 |
16 | test('check button sizes', () => {
17 | const { container } = ENV.render(Button, { size: 'lg' });
18 | const button = container.querySelector('button');
19 | assert.is(button.classList.contains(`btn-lg`), true);
20 | });
21 |
22 | test('check button is active', () => {
23 | const { container } = ENV.render(Button, { active: true });
24 | const button = container.querySelector('button');
25 | assert.is(button.classList.contains(`active`), true);
26 | });
27 |
28 | test('check button is loading', () => {
29 | const { container } = ENV.render(Button, { loading: true });
30 | const button = container.querySelector('button');
31 | assert.is(button.classList.contains(`loading`), true);
32 | });
33 |
34 | test('check button block', () => {
35 | const { container } = ENV.render(Button, { block: true });
36 | const button = container.querySelector('button');
37 | assert.is(button.classList.contains(`btn-block`), true);
38 | });
39 |
40 | test('check button to be a link', () => {
41 | const { container } = ENV.render(Button, { href: 'example.com' });
42 | const a = container.querySelector('a');
43 | assert.is.not(a, null);
44 | });
45 |
46 | test.run();
47 |
--------------------------------------------------------------------------------
/tests/components/Button/Group.spec.ts:
--------------------------------------------------------------------------------
1 | import { test } from 'uvu';
2 | import * as assert from 'uvu/assert';
3 | import * as ENV from '../../setup/testenv';
4 |
5 | import ButtonGroup from '../../../src/lib/components/Button/Group.svelte';
6 |
7 | test.before(ENV.setup);
8 | test.before.each(ENV.reset);
9 |
10 | test('check button-group', () => {
11 | const inline = true;
12 | const { container } = ENV.render(ButtonGroup);
13 | const button = container.querySelector('.btn-group');
14 | assert.is(button.classList.contains(`btn-group`), true);
15 | });
16 |
17 | test('check button-group-block', () => {
18 | const block = true;
19 | const { container } = ENV.render(ButtonGroup, { block });
20 | const button = container.querySelector('.btn-group');
21 | assert.is(button.classList.contains(`btn-group-block`), true);
22 | });
23 |
24 | test.run();
25 |
--------------------------------------------------------------------------------
/tests/components/Button/IconButton.spec.ts:
--------------------------------------------------------------------------------
1 | import { test } from 'uvu';
2 | import * as assert from 'uvu/assert';
3 | import * as ENV from '../../setup/testenv';
4 |
5 | import IconButton from '../../../src/lib/components/Button/IconButton.svelte';
6 |
7 | test.before(ENV.setup);
8 | test.before.each(ENV.reset);
9 |
10 | test('check IconButton icon', () => {
11 | const icon = 'emoji';
12 | const { container } = ENV.render(IconButton, { icon });
13 | const button = container.querySelector('button i');
14 | assert.is(button.classList.contains(`icon-${icon}`), true);
15 | });
16 |
17 | test('check IconButton iconSize', () => {
18 | const iconSize = '1x';
19 | const { container } = ENV.render(IconButton, { iconSize });
20 | const button = container.querySelector('button i');
21 | assert.is(button.classList.contains(`icon-${iconSize}`), true);
22 | });
23 |
24 | test('check IconButton is color', () => {
25 | const color = 'primary';
26 | const { container } = ENV.render(IconButton, { color });
27 | const button = container.querySelector('button i');
28 | assert.is(button.classList.contains(`text-${color}`), true);
29 | });
30 |
31 | test.run();
32 |
--------------------------------------------------------------------------------
/tests/components/Checkbox/Checkbox.spec.ts:
--------------------------------------------------------------------------------
1 | import { test } from 'uvu';
2 | import * as assert from 'uvu/assert';
3 | import * as ENV from '../../setup/testenv';
4 |
5 | import Checkbox from '../../../src/lib/components/Checkbox';
6 |
7 | const links = [
8 | { title: '1', href: '#' },
9 | { title: '2', href: '#' },
10 | { title: '3', href: '#' },
11 | ];
12 |
13 | test.before(ENV.setup);
14 | test.before.each(ENV.reset);
15 |
16 | test('check Checkbox', async () => {
17 | const { container, component } = ENV.render(Checkbox, {
18 | validity: 'success',
19 | inline: true,
20 | value: true,
21 | });
22 | const checkbox: HTMLElement = container.querySelector('.form-checkbox');
23 | const input: HTMLElement = container.querySelector(
24 | 'input[type="checkbox"]'
25 | );
26 | checkbox.append('Checkbox');
27 | await ENV.fire(checkbox, 'click');
28 | // console.log(component);
29 |
30 | assert.is(checkbox.classList.contains(`is-success`), true);
31 | assert.is(checkbox.classList.contains(`form-inline`), true);
32 | assert.is(checkbox.innerHTML.includes(`Checkbox`), true);
33 | // assert.is(input.hasAttribute('checked'), true);
34 | // assert.snapshot(container.innerHTML, 'just render view');
35 | });
36 |
37 | test.run();
38 |
--------------------------------------------------------------------------------
/tests/components/Chip/Chip.spec.ts:
--------------------------------------------------------------------------------
1 | import { test } from 'uvu';
2 | import * as assert from 'uvu/assert';
3 | import * as ENV from '../../setup/testenv';
4 |
5 | import Chip from '../../../src/lib/components/Chip';
6 |
7 | test.before(ENV.setup);
8 | test.before.each(ENV.reset);
9 |
10 | test('check Chip', async () => {
11 | const { container, component } = ENV.render(Chip, {
12 | avatar: true,
13 | name: 'chip chip',
14 | closable: true,
15 | });
16 | const chip: HTMLElement = container.querySelector('.chip');
17 | const avatar: HTMLElement = container.querySelector('.avatar');
18 | const button: HTMLElement = container.querySelector('.btn');
19 | chip.append('Chip');
20 | await ENV.fire(button, 'click');
21 |
22 | assert.is(chip.innerHTML.includes(`Chip`), true);
23 | assert.is(avatar.getAttribute('data-initial'), 'CC');
24 | // assert.snapshot(container.innerHTML, 'just render view');
25 | });
26 |
27 | test.run();
28 |
--------------------------------------------------------------------------------
/tests/components/Divider/Divider.spec.ts:
--------------------------------------------------------------------------------
1 | import { test } from 'uvu';
2 | import * as assert from 'uvu/assert';
3 | import * as ENV from '../../setup/testenv';
4 |
5 | import Divider from '../../../src/lib/components/Divider';
6 |
7 | test.before(ENV.setup);
8 | test.before.each(ENV.reset);
9 |
10 | test('check Divider', async () => {
11 | const { container, component } = ENV.render(Divider, {
12 | align: 'horizontal center',
13 | text: 'divider',
14 | });
15 | const divider: HTMLElement = container.querySelector('.divider');
16 |
17 | assert.is(divider.classList.contains(`text-center`), true);
18 | assert.is(divider.getAttribute('data-content'), 'divider');
19 | // assert.snapshot(container.innerHTML, 'just render view');
20 | });
21 |
22 | test.run();
23 |
--------------------------------------------------------------------------------
/tests/components/Icon/Icon.spec.ts:
--------------------------------------------------------------------------------
1 | import { test } from 'uvu';
2 | import * as assert from 'uvu/assert';
3 | import * as ENV from '../../setup/testenv';
4 |
5 | import Icon from '../../../src/lib/components/Icon';
6 |
7 | test.before(ENV.setup);
8 | test.before.each(ENV.reset);
9 |
10 | test('check Icon', async () => {
11 | const { container, component } = ENV.render(Icon, {
12 | icon: 'emoji',
13 | color: 'primary',
14 | });
15 | const icon: HTMLElement = container.querySelector('.icon');
16 |
17 | assert.is(icon.classList.contains(`icon-emoji`), true);
18 | assert.is(icon.classList.contains(`icon-1x`), true);
19 | assert.is(icon.classList.contains(`text-primary`), true);
20 | // assert.snapshot(container.innerHTML, 'just render view');
21 | });
22 |
23 | test.run();
24 |
--------------------------------------------------------------------------------
/tests/components/Input/Group.spec.ts:
--------------------------------------------------------------------------------
1 | import { test } from 'uvu';
2 | import * as assert from 'uvu/assert';
3 | import * as ENV from '../../setup/testenv';
4 |
5 | import InputGroup from '../../../src/lib/components/Input/Group.svelte';
6 |
7 | test.before(ENV.setup);
8 | test.before.each(ENV.reset);
9 |
10 | test('check Group', async () => {
11 | const { container, component } = ENV.render(InputGroup, {
12 | value: 'input',
13 | color: 'primary',
14 | });
15 | const group: HTMLElement = container.querySelector('.input-group');
16 |
17 | // assert.is(group.classList.contains(`input-group`), true);
18 | // assert.is(icon.classList.contains(`icon-1x`), true);
19 | // assert.snapshot(container.innerHTML, 'just render view');
20 | });
21 |
22 | test.run();
23 |
--------------------------------------------------------------------------------
/tests/components/Input/Input.spec.ts:
--------------------------------------------------------------------------------
1 | import { test } from 'uvu';
2 | import * as assert from 'uvu/assert';
3 | import * as ENV from '../../setup/testenv';
4 |
5 | import Input from '../../../src/lib/components/Input';
6 |
7 | test.before(ENV.setup);
8 | test.before.each(ENV.reset);
9 |
10 | test('check Input', async () => {
11 | const { container, component } = ENV.render(Input, {
12 | value: 'input',
13 | color: 'primary',
14 | });
15 | const input: HTMLInputElement = container.querySelector('.form-input');
16 |
17 | // assert.is(icon.classList.contains(`icon-emoji`), true);
18 | // assert.is(icon.classList.contains(`icon-1x`), true);
19 | assert.is(input.value, 'input');
20 | // assert.snapshot(container.innerHTML, 'just render view');
21 | });
22 |
23 | test.run();
24 |
--------------------------------------------------------------------------------
/tests/components/Pagination/Pagination.spec.ts:
--------------------------------------------------------------------------------
1 | import { test } from 'uvu';
2 | import * as assert from 'uvu/assert';
3 | import * as ENV from '../../setup/testenv';
4 |
5 | import Pagination from '../../../src/lib/components/Pagination';
6 |
7 | test.before(ENV.setup);
8 | test.before.each(ENV.reset);
9 |
10 | test('check Pagination', async () => {
11 | const { container, component } = ENV.render(Pagination, {
12 | total: 100,
13 | limit: 10,
14 | });
15 | const pagination: HTMLElement = container.querySelector('.pagination');
16 |
17 | assert.is(pagination.querySelectorAll(`.page-item`).length, 12);
18 | // assert.snapshot(container.innerHTML, 'just render view');
19 | });
20 |
21 | test.run();
22 |
--------------------------------------------------------------------------------
/tests/components/Progress/Progress.spec.ts:
--------------------------------------------------------------------------------
1 | import { test } from 'uvu';
2 | import * as assert from 'uvu/assert';
3 | import * as ENV from '../../setup/testenv';
4 |
5 | import Progress from '../../../src/lib/components/Progress';
6 |
7 | test.before(ENV.setup);
8 | test.before.each(ENV.reset);
9 |
10 | test('check Progress', async () => {
11 | const { container, component } = ENV.render(Progress, {
12 | color: 'primary',
13 | value: 10,
14 | max: 100,
15 | });
16 | const progress: HTMLElement = container.querySelector('.progress');
17 |
18 | assert.is(progress.classList.contains(`text-primary`), true);
19 | assert.is(progress.getAttribute(`value`), '10');
20 | assert.is(progress.getAttribute(`max`), '100');
21 | // assert.snapshot(container.innerHTML, 'just render view');
22 | });
23 |
24 | test.run();
25 |
--------------------------------------------------------------------------------
/tests/components/Radio/Radio.spec.ts:
--------------------------------------------------------------------------------
1 | import { test } from 'uvu';
2 | import * as assert from 'uvu/assert';
3 | import * as ENV from '../../setup/testenv';
4 |
5 | import Radio from '../../../src/lib/components/Radio';
6 | const radios = [
7 | { name: '1', label: '#' },
8 | { name: '2', label: '#' },
9 | { name: '3', label: '#' },
10 | ];
11 |
12 | test.before(ENV.setup);
13 | test.before.each(ENV.reset);
14 |
15 | test('check Radio', async () => {
16 | const { container, component } = ENV.render(Radio, { radios });
17 | const radio: HTMLElement = container.querySelector('.form-radio');
18 |
19 | assert.is(container.querySelectorAll('.form-radio').length, 3);
20 | // assert.snapshot(container.innerHTML, 'just render view');
21 | });
22 |
23 | test.run();
24 |
--------------------------------------------------------------------------------
/tests/components/Range/Range.spec.ts:
--------------------------------------------------------------------------------
1 | import { test } from 'uvu';
2 | import * as assert from 'uvu/assert';
3 | import * as ENV from '../../setup/testenv';
4 |
5 | import Range from '../../../src/lib/components/Range';
6 |
7 | test.before(ENV.setup);
8 | test.before.each(ENV.reset);
9 |
10 | test('check Range', async () => {
11 | const { container, component } = ENV.render(Range, { range: 10 });
12 | const range: HTMLElement = container.querySelector('[id^=range]');
13 | const input: HTMLInputElement = container.querySelector(
14 | 'input[type="range"]'
15 | );
16 |
17 | assert.is(range.getAttribute('data-range'), '10');
18 | assert.is(input.value, '10');
19 | // assert.snapshot(container.innerHTML, 'just render view');
20 | });
21 |
22 | test.run();
23 |
--------------------------------------------------------------------------------
/tests/components/Select/Select.spec.ts:
--------------------------------------------------------------------------------
1 | import { test } from 'uvu';
2 | import * as assert from 'uvu/assert';
3 | import * as ENV from '../../setup/testenv';
4 |
5 | import Select from '../../../src/lib/components/Select';
6 |
7 | const options = [
8 | { value: '1', label: '#' },
9 | { value: '2', label: '#' },
10 | { value: '3', label: '#' },
11 | ];
12 |
13 | test.before(ENV.setup);
14 | test.before.each(ENV.reset);
15 |
16 | test('check Select', async () => {
17 | const { container, component } = ENV.render(Select, { options });
18 | const select: HTMLElement = container.querySelector('[id^=select]');
19 | const option: HTMLOptionElement[] = container.querySelectorAll('option');
20 |
21 | assert.is(option.length, 3);
22 | // assert.snapshot(container.innerHTML, 'just render view');
23 | });
24 |
25 | test.run();
26 |
--------------------------------------------------------------------------------
/tests/components/Steps/Steps.spec.ts:
--------------------------------------------------------------------------------
1 | import { test } from 'uvu';
2 | import * as assert from 'uvu/assert';
3 | import * as ENV from '../../setup/testenv';
4 |
5 | import Steps from '../../../src/lib/components/Steps';
6 |
7 | const steps = [
8 | { href: '1', label: '#' },
9 | { href: '2', label: '#' },
10 | { href: '3', label: '#' },
11 | ];
12 |
13 | test.before(ENV.setup);
14 | test.before.each(ENV.reset);
15 |
16 | test('check Steps', async () => {
17 | const { container, component } = ENV.render(Steps, { steps });
18 | const step: HTMLElement = container.querySelector('.step');
19 | const items: HTMLElement[] = container.querySelectorAll('.step-item');
20 |
21 | assert.is(items.length, 3);
22 | // assert.snapshot(container.innerHTML, 'just render view');
23 | });
24 |
25 | test.run();
26 |
--------------------------------------------------------------------------------
/tests/components/Switch/Switch.spec.ts:
--------------------------------------------------------------------------------
1 | import { test } from 'uvu';
2 | import * as assert from 'uvu/assert';
3 | import * as ENV from '../../setup/testenv';
4 |
5 | import Switch from '../../../src/lib/components/Switch';
6 |
7 | test.before(ENV.setup);
8 | test.before.each(ENV.reset);
9 |
10 | test('check Switch', async () => {
11 | const { container, component } = ENV.render(Switch, { inline: true });
12 | const swich: HTMLElement = container.querySelector('.form-switch');
13 | const input: HTMLInputElement = container.querySelector(
14 | 'input[type="checkbox"]'
15 | );
16 | swich.append('Switch');
17 |
18 | assert.is(swich.classList.contains('form-inline'), true);
19 | assert.is(swich.innerHTML.includes('Switch'), true);
20 | // assert.snapshot(container.innerHTML, 'just render view');
21 | });
22 |
23 | test.run();
24 |
--------------------------------------------------------------------------------
/tests/components/Tabs/Tabs.spec.ts:
--------------------------------------------------------------------------------
1 | import { test } from 'uvu';
2 | import * as assert from 'uvu/assert';
3 | import * as ENV from '../../setup/testenv';
4 |
5 | import Tabs from '../../../src/lib/components/Tabs';
6 |
7 | const items = [
8 | { href: '1', label: '#' },
9 | { href: '2', label: '#' },
10 | { href: '3', label: '#' },
11 | ];
12 |
13 | test.before(ENV.setup);
14 | test.before.each(ENV.reset);
15 |
16 | test('check Tabs', async () => {
17 | const { container, component } = ENV.render(Tabs, { items });
18 | const tabs: HTMLElement = container.querySelector('.tab');
19 |
20 | assert.is(tabs.querySelectorAll('.tab-item').length, 3);
21 | // assert.snapshot(container.innerHTML, 'just render view');
22 | });
23 |
24 | test.run();
25 |
--------------------------------------------------------------------------------
/tests/components/Toast/Toast.spec.ts:
--------------------------------------------------------------------------------
1 | import { test } from 'uvu';
2 | import * as assert from 'uvu/assert';
3 | import * as ENV from '../../setup/testenv';
4 |
5 | import Toast from '../../../src/lib/components/Toast/Toast.svelte';
6 | const toastItem = { invert: false, close: true, icon: 'emoji', timeout: 1000 };
7 |
8 | test.before(ENV.setup);
9 | test.before.each(ENV.reset);
10 |
11 | test('check Toast', () => {
12 | const { container, component } = ENV.render(Toast, { toastItem });
13 | const toast = container.querySelector('.toast');
14 | toast.querySelector('.toast-content').innerHTML = 'Default text';
15 | assert.is(toast.innerHTML.includes(`Default text`), true);
16 | // assert.snapshot(container.innerHTML, 'just render view');
17 | });
18 |
19 | test.run();
20 |
--------------------------------------------------------------------------------
/tests/components/Transition/Transition.spec.ts:
--------------------------------------------------------------------------------
1 | import { test } from 'uvu';
2 | import * as assert from 'uvu/assert';
3 | import * as ENV from '../../setup/testenv';
4 |
5 | import Transition from '../../../src/lib/components/Transition';
6 |
7 | test.before(ENV.setup);
8 | test.before.each(ENV.reset);
9 |
10 | test('check Transition', async () => {
11 | const { container, component } = ENV.render(Transition, {
12 | in: 'slide',
13 | out: 'fade',
14 | });
15 | // const tabs: HTMLElement = container.querySelector('.tab');
16 |
17 | // assert.is(tabs.querySelectorAll('.tab-item').length, 3);
18 | // assert.snapshot(container.innerHTML, 'just render view');
19 | });
20 |
21 | test.run();
22 |
--------------------------------------------------------------------------------
/tests/layouts/Card/Card.spec.ts:
--------------------------------------------------------------------------------
1 | import { test } from 'uvu';
2 | import * as assert from 'uvu/assert';
3 | import * as ENV from '../../setup/testenv';
4 |
5 | import Card from '../../../src/lib/layouts/Card';
6 |
7 | test.before(ENV.setup);
8 | test.before.each(ENV.reset);
9 |
10 | test('check Card', async () => {
11 | const { container, component } = ENV.render(Card, {
12 | // title: 'card',
13 | });
14 | const card: HTMLElement = container.querySelector('.card');
15 | // const summary: HTMLElement = container.querySelector('.card-header');
16 | // await ENV.fire(summary, 'click');
17 | // card.querySelector('.card-body').innerHTML = 'card-body';
18 |
19 | assert.is(card.classList.contains(`card`), true);
20 | // assert.snapshot(container.innerHTML, 'just render view');
21 | });
22 |
23 | test.run();
24 |
--------------------------------------------------------------------------------
/tests/layouts/Code/Code.spec.ts:
--------------------------------------------------------------------------------
1 | import { test } from 'uvu';
2 | import * as assert from 'uvu/assert';
3 | import * as ENV from '../../setup/testenv';
4 |
5 | import Code from '../../../src/lib/layouts/Code';
6 |
7 | test.before(ENV.setup);
8 | test.before.each(ENV.reset);
9 |
10 | test('check Code', async () => {
11 | const { container, component } = ENV.render(Code, {
12 | // title: 'code',
13 | });
14 | const code: HTMLElement = container.querySelector('.code');
15 | // const summary: HTMLElement = container.querySelector('.code-header');
16 | // await ENV.fire(summary, 'click');
17 | // code.querySelector('.code-body').innerHTML = 'code-body';
18 |
19 | assert.is(code.classList.contains(`code`), true);
20 | // assert.snapshot(container.innerHTML, 'just render view');
21 | });
22 |
23 | test.run();
24 |
--------------------------------------------------------------------------------
/tests/layouts/Container/Container.spec.ts:
--------------------------------------------------------------------------------
1 | import { test } from 'uvu';
2 | import * as assert from 'uvu/assert';
3 | import * as ENV from '../../setup/testenv';
4 |
5 | import Container from '../../../src/lib/layouts/Container';
6 |
7 | test.before(ENV.setup);
8 | test.before.each(ENV.reset);
9 |
10 | test('check Container', async () => {
11 | const { container, component } = ENV.render(Container, {
12 | // title: 'Code',
13 | });
14 | const containers: HTMLElement = container.querySelector('.container');
15 | // const summary: HTMLElement = container.querySelector('.code-header');
16 | // await ENV.fire(summary, 'click');
17 | // code.querySelector('.code-body').innerHTML = 'code-body';
18 |
19 | assert.is(containers.classList.contains(`container`), true);
20 | // assert.snapshot(container.innerHTML, 'just render view');
21 | });
22 |
23 | test.run();
24 |
--------------------------------------------------------------------------------
/tests/layouts/Dropdown/Dropdown.spec.ts:
--------------------------------------------------------------------------------
1 | import { test } from 'uvu';
2 | import * as assert from 'uvu/assert';
3 | import * as ENV from '../../setup/testenv';
4 |
5 | import Dropdown from '../../../src/lib/layouts/Dropdown';
6 |
7 | test.before(ENV.setup);
8 | test.before.each(ENV.reset);
9 |
10 | test('check Dropdown', async () => {
11 | const { container, component } = ENV.render(Dropdown, {
12 | // title: 'Code',
13 | });
14 | const dropdown: HTMLElement = container.querySelector('.dropdown');
15 | // const summary: HTMLElement = container.querySelector('.code-header');
16 | // await ENV.fire(summary, 'click');
17 | // code.querySelector('.code-body').innerHTML = 'code-body';
18 |
19 | assert.is(dropdown.classList.contains(`dropdown`), true);
20 | // assert.snapshot(container.innerHTML, 'just render view');
21 | });
22 |
23 | test.run();
24 |
--------------------------------------------------------------------------------
/tests/layouts/Empty/Empty.spec.ts:
--------------------------------------------------------------------------------
1 | import { test } from 'uvu';
2 | import * as assert from 'uvu/assert';
3 | import * as ENV from '../../setup/testenv';
4 |
5 | import Empty from '../../../src/lib/layouts/Empty';
6 |
7 | test.before(ENV.setup);
8 | test.before.each(ENV.reset);
9 |
10 | test('check Empty', async () => {
11 | const { container, component } = ENV.render(Empty, {
12 | // title: 'Code',
13 | });
14 | const empty: HTMLElement = container.querySelector('.empty');
15 | // const summary: HTMLElement = container.querySelector('.code-header');
16 | // await ENV.fire(summary, 'click');
17 | // code.querySelector('.code-body').innerHTML = 'code-body';
18 |
19 | assert.is(empty.classList.contains(`empty`), true);
20 | // assert.snapshot(container.innerHTML, 'just render view');
21 | });
22 |
23 | test.run();
24 |
--------------------------------------------------------------------------------
/tests/layouts/Figure/Figure.spec.ts:
--------------------------------------------------------------------------------
1 | import { test } from 'uvu';
2 | import * as assert from 'uvu/assert';
3 | import * as ENV from '../../setup/testenv';
4 |
5 | import Figure from '../../../src/lib/layouts/Figure';
6 |
7 | test.before(ENV.setup);
8 | test.before.each(ENV.reset);
9 |
10 | test('check Figure', async () => {
11 | const { container, component } = ENV.render(Figure, {
12 | // title: 'Code',
13 | });
14 | const figure: HTMLElement = container.querySelector('.figure');
15 | // const summary: HTMLElement = container.querySelector('.code-header');
16 | // await ENV.fire(summary, 'click');
17 | // code.querySelector('.code-body').innerHTML = 'code-body';
18 |
19 | assert.is(figure.classList.contains(`figure`), true);
20 | // assert.snapshot(container.innerHTML, 'just render view');
21 | });
22 |
23 | test.run();
24 |
--------------------------------------------------------------------------------
/tests/layouts/Form/Form.spec.ts:
--------------------------------------------------------------------------------
1 | import { test } from 'uvu';
2 | import * as assert from 'uvu/assert';
3 | import * as ENV from '../../setup/testenv';
4 |
5 | import Form from '../../../src/lib/layouts/Form';
6 |
7 | test.before(ENV.setup);
8 | test.before.each(ENV.reset);
9 |
10 | test('check Form', async () => {
11 | const { container, component } = ENV.render(Form, {
12 | // title: 'Code',
13 | });
14 | const form: HTMLElement = container.querySelector('form');
15 | // const summary: HTMLElement = container.querySelector('.code-header');
16 | // await ENV.fire(summary, 'click');
17 | // code.querySelector('.code-body').innerHTML = 'code-body';
18 |
19 | assert.is(container.contains(form), true);
20 | // assert.snapshot(container.innerHTML, 'just render view');
21 | });
22 |
23 | test.run();
24 |
--------------------------------------------------------------------------------
/tests/layouts/Form/FormGroup.spec.ts:
--------------------------------------------------------------------------------
1 | import { test } from 'uvu';
2 | import * as assert from 'uvu/assert';
3 | import * as ENV from '../../setup/testenv';
4 |
5 | import { FormGroup } from '../../../src/lib/layouts/Form';
6 |
7 | test.before(ENV.setup);
8 | test.before.each(ENV.reset);
9 |
10 | test('check FormGroup', async () => {
11 | const { container, component } = ENV.render(FormGroup, {
12 | // title: 'Code',
13 | });
14 | const formGroup: HTMLElement = container.querySelector('.form-group');
15 | // const summary: HTMLElement = container.querySelector('.code-header');
16 | // await ENV.fire(summary, 'click');
17 | // code.querySelector('.code-body').innerHTML = 'code-body';
18 |
19 | assert.is(formGroup.classList.contains(`form-group`), true);
20 | assert.is(container.contains(formGroup), true);
21 | // assert.snapshot(container.innerHTML, 'just render view');
22 | });
23 |
24 | test.run();
25 |
--------------------------------------------------------------------------------
/tests/layouts/Grid/Col.spec.ts:
--------------------------------------------------------------------------------
1 | import { test } from 'uvu';
2 | import * as assert from 'uvu/assert';
3 | import * as ENV from '../../setup/testenv';
4 |
5 | import { Col } from '../../../src/lib/layouts/Grid';
6 |
7 | test.before(ENV.setup);
8 | test.before.each(ENV.reset);
9 |
10 | test('check Col', async () => {
11 | const { container, component } = ENV.render(Col, {
12 | // title: 'Code',
13 | });
14 | const column: HTMLElement = container.querySelector('.column');
15 | // const summary: HTMLElement = container.querySelector('.code-header');
16 | // await ENV.fire(summary, 'click');
17 | // code.querySelector('.code-body').innerHTML = 'code-body';
18 |
19 | assert.is(column.classList.contains(`column`), true);
20 | // assert.snapshot(container.innerHTML, 'just render view');
21 | });
22 |
23 | test.run();
24 |
--------------------------------------------------------------------------------
/tests/layouts/Grid/Grid.spec.ts:
--------------------------------------------------------------------------------
1 | import { test } from 'uvu';
2 | import * as assert from 'uvu/assert';
3 | import * as ENV from '../../setup/testenv';
4 |
5 | import { Grid } from '../../../src/lib/layouts/Grid';
6 |
7 | test.before(ENV.setup);
8 | test.before.each(ENV.reset);
9 |
10 | test('check Grid', async () => {
11 | const { container, component } = ENV.render(Grid, {
12 | // title: 'Code',
13 | });
14 | const grid: HTMLElement = container.querySelector('.columns');
15 | // const summary: HTMLElement = container.querySelector('.code-header');
16 | // await ENV.fire(summary, 'click');
17 | // code.querySelector('.code-body').innerHTML = 'code-body';
18 |
19 | assert.is(grid.classList.contains(`columns`), true);
20 | // assert.snapshot(container.innerHTML, 'just render view');
21 | });
22 |
23 | test.run();
24 |
--------------------------------------------------------------------------------
/tests/layouts/Hero/Hero.spec.ts:
--------------------------------------------------------------------------------
1 | import { test } from 'uvu';
2 | import * as assert from 'uvu/assert';
3 | import * as ENV from '../../setup/testenv';
4 |
5 | import Hero from '../../../src/lib/layouts/Hero';
6 |
7 | test.before(ENV.setup);
8 | test.before.each(ENV.reset);
9 |
10 | test('check Hero', async () => {
11 | const { container, component } = ENV.render(Hero, {
12 | // title: 'Code',
13 | });
14 | const hero: HTMLElement = container.querySelector('.hero');
15 | // const summary: HTMLElement = container.querySelector('.code-header');
16 | // await ENV.fire(summary, 'click');
17 | // code.querySelector('.code-body').innerHTML = 'code-body';
18 |
19 | assert.is(hero.classList.contains(`hero`), true);
20 | // assert.snapshot(container.innerHTML, 'just render view');
21 | });
22 |
23 | test.run();
24 |
--------------------------------------------------------------------------------
/tests/layouts/Modal/Modal.spec.ts:
--------------------------------------------------------------------------------
1 | import { test } from 'uvu';
2 | import * as assert from 'uvu/assert';
3 | import * as ENV from '../../setup/testenv';
4 |
5 | import Modal from '../../../src/lib/layouts/Modal';
6 |
7 | test.before(ENV.setup);
8 | test.before.each(ENV.reset);
9 |
10 | test('check Modal', async () => {
11 | const { container, component } = ENV.render(Modal, {
12 | // title: 'Code',
13 | });
14 | const modal: HTMLElement = container.querySelector('.modal');
15 | // const summary: HTMLElement = container.querySelector('.code-header');
16 | // await ENV.fire(summary, 'click');
17 | // code.querySelector('.code-body').innerHTML = 'code-body';
18 |
19 | assert.is(modal.classList.contains(`modal`), true);
20 | // assert.snapshot(container.innerHTML, 'just render view');
21 | });
22 |
23 | test.run();
24 |
--------------------------------------------------------------------------------
/tests/layouts/Navbar/Navbar.spec.ts:
--------------------------------------------------------------------------------
1 | import { test } from 'uvu';
2 | import * as assert from 'uvu/assert';
3 | import * as ENV from '../../setup/testenv';
4 |
5 | import Navbar from '../../../src/lib/layouts/Navbar';
6 |
7 | test.before(ENV.setup);
8 | test.before.each(ENV.reset);
9 |
10 | test('check Navbar', async () => {
11 | const { container, component } = ENV.render(Navbar, {
12 | // title: 'Code',
13 | });
14 | const navbar: HTMLElement = container.querySelector('.navbar');
15 | // const summary: HTMLElement = container.querySelector('.code-header');
16 | // await ENV.fire(summary, 'click');
17 | // code.querySelector('.code-body').innerHTML = 'code-body';
18 |
19 | assert.is(navbar.classList.contains(`navbar`), true);
20 | // assert.snapshot(container.innerHTML, 'just render view');
21 | });
22 |
23 | test.run();
24 |
--------------------------------------------------------------------------------
/tests/layouts/Panel/Panel.spec.ts:
--------------------------------------------------------------------------------
1 | import { test } from 'uvu';
2 | import * as assert from 'uvu/assert';
3 | import * as ENV from '../../setup/testenv';
4 |
5 | import Panel from '../../../src/lib/layouts/Panel';
6 |
7 | test.before(ENV.setup);
8 | test.before.each(ENV.reset);
9 |
10 | test('check Panel', async () => {
11 | const { container, component } = ENV.render(Panel, {
12 | // title: 'Code',
13 | });
14 | const panel: HTMLElement = container.querySelector('.panel');
15 | // const summary: HTMLElement = container.querySelector('.code-header');
16 | // await ENV.fire(summary, 'click');
17 | // code.querySelector('.code-body').innerHTML = 'code-body';
18 |
19 | assert.is(panel.classList.contains(`panel`), true);
20 | // assert.snapshot(container.innerHTML, 'just render view');
21 | });
22 |
23 | test.run();
24 |
--------------------------------------------------------------------------------
/tests/layouts/Popover/Popover.spec.ts:
--------------------------------------------------------------------------------
1 | import { test } from 'uvu';
2 | import * as assert from 'uvu/assert';
3 | import * as ENV from '../../setup/testenv';
4 |
5 | import Popover from '../../../src/lib/layouts/Popover';
6 |
7 | test.before(ENV.setup);
8 | test.before.each(ENV.reset);
9 |
10 | test('check Popover', async () => {
11 | const { container, component } = ENV.render(Popover, {
12 | // title: 'Code',
13 | });
14 | const popover: HTMLElement = container.querySelector('.popover');
15 | // const summary: HTMLElement = container.querySelector('.code-header');
16 | // await ENV.fire(summary, 'click');
17 | // code.querySelector('.code-body').innerHTML = 'code-body';
18 |
19 | assert.is(popover.classList.contains(`popover`), true);
20 | // assert.snapshot(container.innerHTML, 'just render view');
21 | });
22 |
23 | test.run();
24 |
--------------------------------------------------------------------------------
/tests/layouts/Sidebar/Sidebar.spec.ts:
--------------------------------------------------------------------------------
1 | import { test } from 'uvu';
2 | import * as assert from 'uvu/assert';
3 | import * as ENV from '../../setup/testenv';
4 |
5 | import Sidebar from '../../../src/lib/layouts/Sidebar';
6 |
7 | test.before(ENV.setup);
8 | test.before.each(ENV.reset);
9 |
10 | test('check Sidebar', async () => {
11 | const { container, component } = ENV.render(Sidebar, {
12 | // title: 'Code',
13 | });
14 | const sidebar: HTMLElement = container.querySelector('.off-canvas');
15 | // const summary: HTMLElement = container.querySelector('.code-header');
16 | // await ENV.fire(summary, 'click');
17 | // code.querySelector('.code-body').innerHTML = 'code-body';
18 |
19 | assert.is(sidebar.classList.contains(`off-canvas`), true);
20 | // assert.snapshot(container.innerHTML, 'just render view');
21 | });
22 |
23 | test.run();
24 |
--------------------------------------------------------------------------------
/tests/layouts/Tile/Tile.spec.ts:
--------------------------------------------------------------------------------
1 | import { test } from 'uvu';
2 | import * as assert from 'uvu/assert';
3 | import * as ENV from '../../setup/testenv';
4 |
5 | import Tile from '../../../src/lib/layouts/Tile';
6 |
7 | test.before(ENV.setup);
8 | test.before.each(ENV.reset);
9 |
10 | test('check Tile', async () => {
11 | const { container, component } = ENV.render(Tile, {
12 | // title: 'Code',
13 | });
14 | const tile: HTMLElement = container.querySelector('.tile');
15 | // const summary: HTMLElement = container.querySelector('.code-header');
16 | // await ENV.fire(summary, 'click');
17 | // code.querySelector('.code-body').innerHTML = 'code-body';
18 |
19 | assert.is(tile.innerHTML.includes(`tile`), true);
20 | // assert.snapshot(container.innerHTML, 'just render view');
21 | });
22 |
23 | test.run();
24 |
--------------------------------------------------------------------------------
/tests/setup/preprocess.js:
--------------------------------------------------------------------------------
1 | import { preprocess } from 'svelte/compiler';
2 | import { pathToFileURL } from 'url';
3 |
4 | const { source, filename, svelteConfig } = process.env;
5 |
6 | import(pathToFileURL(svelteConfig).toString())
7 | .then((configImport) => {
8 | const config = configImport.default ? configImport.default : configImport;
9 |
10 | preprocess(source, config.preprocess || {}, { filename }).then((r) =>
11 | process.stdout.write(r.code)
12 | );
13 | })
14 | .catch((err) => process.stderr.write(err));
15 |
--------------------------------------------------------------------------------
/tests/setup/register.js:
--------------------------------------------------------------------------------
1 | import { addHook } from 'pirates';
2 | import { transform } from './transformer';
3 |
4 | const handleSvelte = (source, filename) => transform(source, filename);
5 |
6 | addHook(handleSvelte, { exts: ['.svelte'] });
7 |
--------------------------------------------------------------------------------
/tests/setup/slots.js:
--------------------------------------------------------------------------------
1 | import { noop, insert, detach } from 'svelte/internal';
2 |
3 | function create_root_slot_fn(elements) {
4 | return function () {
5 | return {
6 | c: noop,
7 |
8 | m: function mount(target, anchor) {
9 | elements.forEach((element) => {
10 | insert(target, element, anchor);
11 | });
12 | },
13 |
14 | d: function destroy(detaching) {
15 | if (detaching) {
16 | elements.forEach(detach);
17 | }
18 | },
19 |
20 | l: noop,
21 | };
22 | };
23 | }
24 |
25 | export function createSlot(input) {
26 | var key,
27 | tmp,
28 | slots = {};
29 | for (key in input) {
30 | tmp = input[key];
31 | slots[key] = [create_root_slot_fn(Array.isArray(tmp) ? tmp : [tmp])];
32 | }
33 | return slots;
34 | }
35 |
36 | // USE ----------------------------------
37 |
38 | import { createSlot } from 'svelte/slot';
39 |
40 | export default {
41 | options(window) {
42 | const default_el = window.document.createElement('div');
43 | default_el.innerHTML = 'default slot custom content';
44 | const my_slot_el1 = window.document.createElement('div');
45 | my_slot_el1.innerHTML = 'first my slot element';
46 | const my_slot_el2 = window.document.createElement('div');
47 | my_slot_el2.innerHTML = 'second my slot element';
48 | const my_slot_els = [my_slot_el1, my_slot_el2];
49 | const another_slot_el = window.document.createTextNode('another slot');
50 | const conditional_slot_el = window.document.createElement('div');
51 | conditional_slot_el.innerHTML = 'conditional slot';
52 | return {
53 | slots: {
54 | slots: createSlot({
55 | default: default_el,
56 | 'my-slot': my_slot_els,
57 | 'another-slot-with-content': another_slot_el,
58 | 'conditional-slot': conditional_slot_el,
59 | }),
60 | },
61 | };
62 | },
63 |
64 | test({ assert, component, target }) {
65 | assert.htmlEqual(
66 | target.innerHTML,
67 | `
68 | default slot: default slot custom content
69 | named slot: first my slot element
second my slot element
70 | slot with default content: default content
71 | another slot with content: another slot
72 | conditional slot: conditional slot
73 | conditional slot with content: default content`
74 | );
75 | component.is_slot_visible = false;
76 | assert.htmlEqual(
77 | target.innerHTML,
78 | `
79 | default slot: default slot custom content
80 | named slot: first my slot element
second my slot element
81 | slot with default content: default content
82 | another slot with content: another slot`
83 | );
84 | component.is_slot_visible = true;
85 | assert.htmlEqual(
86 | target.innerHTML,
87 | `
88 | default slot: default slot custom content
89 | named slot: first my slot element
second my slot element
90 | slot with default content: default content
91 | another slot with content: another slot
92 | conditional slot: conditional slot
93 | conditional slot with content: default content`
94 | );
95 | },
96 | };
97 |
--------------------------------------------------------------------------------
/tests/setup/svelteconfig.js:
--------------------------------------------------------------------------------
1 | import { existsSync } from 'fs';
2 | import { dirname, resolve, join } from 'path';
3 |
4 | const configFilename = 'svelte.config.js';
5 |
6 | export function getSvelteConfig(rootMode, filename) {
7 | const configDir = rootMode === 'upward' ? getConfigDir(dirname(filename)) : process.cwd();
8 |
9 | const configFile = resolve(configDir, configFilename);
10 |
11 | if (!existsSync(configFile)) {
12 | throw Error(`Could not find ${configFilename}`);
13 | }
14 |
15 | return configFile;
16 | }
17 |
18 | const getConfigDir = (searchDir) => {
19 | if (existsSync(join(searchDir, configFilename))) {
20 | return searchDir;
21 | }
22 |
23 | const parentDir = resolve(searchDir, '..');
24 |
25 | return parentDir !== searchDir ? getConfigDir(parentDir) : searchDir; // Stop walking at filesystem root
26 | };
27 |
--------------------------------------------------------------------------------
/tests/setup/transformer.js:
--------------------------------------------------------------------------------
1 | import { parse } from 'path';
2 | import { execSync } from 'child_process';
3 | import { compile } from 'svelte/compiler';
4 | import { getSvelteConfig } from './svelteconfig';
5 |
6 | const processSync =
7 | (options = {}) =>
8 | (source, filename) => {
9 | const { debug, preprocess, rootMode } = options;
10 | let processed = source;
11 | if (preprocess) {
12 | const svelteConfig = getSvelteConfig(rootMode, filename);
13 | const preprocessor = require.resolve('./preprocess.js');
14 | processed = execSync(
15 | `node --unhandled-rejections=strict --abort-on-uncaught-exception "${preprocessor}"`,
16 | { env: { PATH: process.env.PATH, source, filename, svelteConfig } }
17 | ).toString();
18 | if (debug) console.log(processed);
19 | return processed;
20 | } else {
21 | return source;
22 | }
23 | };
24 |
25 | const transform = (source, filename) => {
26 | const { name } = parse(filename);
27 |
28 | const preprocessed = processSync({ preprocess: true })(source, filename);
29 |
30 | const { js, warnings } = compile(preprocessed, {
31 | name: name[0].toUpperCase() + name.slice(1),
32 | format: 'cjs',
33 | filename,
34 | });
35 |
36 | warnings.forEach((warning) => {
37 | console.warn('\x1b[37m%s\x1b[0m', `\n${warning.filename}:`);
38 | console.warn('\x1b[33m%s\x1b[0m', warning.message);
39 | console.warn('\x1b[90m%s\x1b[0m', warning.frame);
40 | });
41 |
42 | return js.code;
43 | };
44 |
45 | export { transform };
46 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./.svelte-kit/tsconfig.json",
3 | "compilerOptions": {
4 | "moduleResolution": "node",
5 | "module": "ESNext",
6 | "lib": [
7 | "ESNext",
8 | "DOM"
9 | ],
10 | "target": "ESNext",
11 | "importsNotUsedAsValues": "error",
12 | "preserveValueImports": true,
13 | "isolatedModules": true,
14 | "resolveJsonModule": true,
15 | "sourceMap": true,
16 | "esModuleInterop": true,
17 | "skipLibCheck": true,
18 | "forceConsistentCasingInFileNames": true,
19 | "baseUrl": ".",
20 | "allowJs": true,
21 | "checkJs": true,
22 | "strict": true,
23 | "paths": {
24 | "$lib": [
25 | "src/lib"
26 | ],
27 | "$lib/*": [
28 | "src/lib/*"
29 | ],
30 | "$svelte-spectre": [
31 | "package/index.js"
32 | ]
33 | }
34 | },
35 | "include": [
36 | "src/**/*.js",
37 | "src/**/*.ts",
38 | "src/**/*.svelte"
39 | ],
40 | "exclude": [
41 | "node_modules/**",
42 | "src/**/*.spec.ts"
43 | ]
44 | }
45 |
--------------------------------------------------------------------------------
/vite.config.js:
--------------------------------------------------------------------------------
1 | import fs from 'fs';
2 | import path from 'path';
3 | import { sveltekit } from '@sveltejs/kit/vite';
4 | import svg from '@poppanator/sveltekit-svg';
5 |
6 | const pkg = JSON.parse(fs.readFileSync(new URL('package.json', import.meta.url), 'utf8'));
7 |
8 | process.env.VITE_APP_NAME = pkg.name;
9 | process.env.VITE_APP_VERSION = pkg.version;
10 | process.env.VITE_APP_GIT = pkg.repository.url.replace(/git\+|\.git/g, '');
11 |
12 | /** @type {import('vite').UserConfig} */
13 | const config = {
14 | resolve: {
15 | alias: {
16 | $assets: path.resolve('./src/www/assets'),
17 | },
18 | },
19 | server: {
20 | port: 3030,
21 | },
22 | plugins: [sveltekit(), svg()],
23 | };
24 |
25 | export default config;
26 |
--------------------------------------------------------------------------------