jabroni-outfit 1.6.4 → 2.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of jabroni-outfit might be problematic. Click here for more details.

Files changed (47) hide show
  1. package/README.md +68 -108
  2. package/dist/index.d.ts +148 -62
  3. package/dist/jabroni-outfit.es.js +3804 -2969
  4. package/dist/jabroni-outfit.es.js.map +1 -1
  5. package/dist/jabroni-outfit.umd.js +13 -16
  6. package/dist/jabroni-outfit.umd.js.map +1 -1
  7. package/package.json +18 -18
  8. package/src/app.ts +39 -0
  9. package/src/components/App.vue +40 -0
  10. package/src/components/Badge.vue +30 -0
  11. package/src/components/Chevron.vue +10 -0
  12. package/src/components/Header.vue +38 -0
  13. package/src/components/RowButton.vue +21 -0
  14. package/src/components/Section.vue +66 -0
  15. package/src/components/icons/Check.vue +17 -0
  16. package/src/components/icons/ChevronDown.vue +17 -0
  17. package/src/components/icons/ChevronUp.vue +17 -0
  18. package/src/components/icons/Minus.vue +17 -0
  19. package/src/components/icons/Sun.vue +21 -0
  20. package/src/components/inputs/InputCheckbox.vue +29 -0
  21. package/src/components/inputs/InputNumber.vue +24 -0
  22. package/src/components/inputs/InputRange.vue +66 -0
  23. package/src/components/inputs/InputText.vue +21 -0
  24. package/src/index.ts +4 -17
  25. package/src/scheme/default-scheme.ts +129 -0
  26. package/src/scheme/parser.ts +103 -0
  27. package/src/scheme/scheme-element.ts +93 -0
  28. package/src/store/default-state.ts +8 -37
  29. package/src/store/index.ts +63 -0
  30. package/src/store/persistent-state.ts +45 -17
  31. package/src/style/index.css +30 -0
  32. package/src/test/example.ts +56 -44
  33. package/src/test/umd-example.js +58 -27
  34. package/src/types/index.ts +48 -0
  35. package/src/utils/index.ts +33 -0
  36. package/src/store/store.ts +0 -52
  37. package/src/store/types.ts +0 -16
  38. package/src/style.css +0 -3
  39. package/src/typings/vue.d.ts +0 -6
  40. package/src/ui/default-scheme.ts +0 -76
  41. package/src/ui/index.ts +0 -31
  42. package/src/ui/types.ts +0 -27
  43. package/src/ui/vue-templates/App.vue +0 -48
  44. package/src/ui/vue-templates/Gen.vue +0 -21
  45. package/src/ui/vue-templates/RowElement.vue +0 -66
  46. package/src/ui/vue-templates/icons/Close.vue +0 -7
  47. package/src/ui/vue-templates/icons/Config.vue +0 -7
@@ -0,0 +1,129 @@
1
+ import type { ExtractValuesByKey, SchemeInput } from '../types';
2
+
3
+ export const DefaultScheme = [
4
+ {
5
+ title: 'Text Filter',
6
+ collapsed: true,
7
+ content: [
8
+ { filterExclude: false, label: 'exclude' },
9
+ {
10
+ filterExcludeWords: '',
11
+ label: 'keywords',
12
+ watch: 'filterExclude',
13
+ placeholder: 'word, word1|word2, f:full_word...',
14
+ },
15
+ { filterInclude: false, label: 'include' },
16
+ {
17
+ filterIncludeWords: '',
18
+ label: 'keywords',
19
+ watch: 'filterInclude',
20
+ placeholder: 'word, word1|word2, f:full_word...',
21
+ },
22
+ ],
23
+ },
24
+ {
25
+ title: 'Duration Filter',
26
+ collapsed: true,
27
+ content: [
28
+ { filterDuration: false, label: 'enable' },
29
+ { filterDurationMinutes: true, label: 'minutes (seconds by default)' },
30
+ {
31
+ filterDurationFrom: 0,
32
+ watch: 'filterDuration',
33
+ label: 'from',
34
+ },
35
+ {
36
+ filterDurationTo: 600,
37
+ watch: 'filterDuration',
38
+ label: 'to',
39
+ },
40
+ ],
41
+ },
42
+ {
43
+ title: 'Sort By',
44
+ content: [
45
+ {
46
+ views: () => {
47
+ //@ts-expect-error
48
+ window.sortByViews?.();
49
+ },
50
+ },
51
+ {
52
+ duration: () => {
53
+ //@ts-expect-error
54
+ window.sortByDuration?.();
55
+ },
56
+ },
57
+ ],
58
+ },
59
+ {
60
+ title: 'Privacy Filter',
61
+ content: [
62
+ { filterPrivate: false, label: 'private' },
63
+ { filterPublic: false, label: 'public' },
64
+ {
65
+ 'check access 🔓': () => {
66
+ //@ts-expect-error
67
+ window.requestAccess?.();
68
+ },
69
+ },
70
+ ],
71
+ },
72
+ {
73
+ title: 'Quality Filter',
74
+ content: [{ filterHD: false, label: 'HD' }],
75
+ },
76
+ {
77
+ title: 'Advanced',
78
+ content: [
79
+ {
80
+ infiniteScrollEnabled: true,
81
+ label: 'infinite scroll',
82
+ },
83
+ {
84
+ autoRequestAccess: false,
85
+ label: 'auto friend request',
86
+ },
87
+ {
88
+ writeHistory: false,
89
+ },
90
+ ],
91
+ },
92
+ {
93
+ // Pagination
94
+ title: 'Badge',
95
+ content: [
96
+ {
97
+ text: 'return `${state.$paginationOffset}/${state.$paginationLast}`',
98
+ vif: 'return state.$paginationLast > 1',
99
+ },
100
+ ],
101
+ },
102
+ ] as const satisfies SchemeInput;
103
+
104
+ function selectFromScheme(keys: string[], scheme: SchemeInput): SchemeInput {
105
+ return scheme.filter((g) => g.title && keys.some((k) => k === g.title));
106
+ }
107
+
108
+ export function setupScheme<
109
+ K extends ExtractValuesByKey<typeof DefaultScheme, 'title'>,
110
+ T extends SchemeInput,
111
+ TK extends ExtractValuesByKey<T, 'title'>,
112
+ >(
113
+ selectFromDefaults: K[],
114
+ customScheme: T = [] as unknown as T,
115
+ order?: (K | TK)[],
116
+ ) {
117
+ const selectedScheme: SchemeInput = selectFromScheme(
118
+ selectFromDefaults,
119
+ DefaultScheme,
120
+ );
121
+
122
+ selectedScheme.push(...customScheme);
123
+
124
+ if (order) {
125
+ return selectFromScheme(order, selectedScheme);
126
+ }
127
+
128
+ return selectedScheme;
129
+ }
@@ -0,0 +1,103 @@
1
+ import { JabronioStore } from '../store';
2
+ import type {
3
+ RawSchemeElement,
4
+ SchemeGroup,
5
+ SchemeInput,
6
+ SchemeParsed,
7
+ SchemeSection,
8
+ } from '../types';
9
+ import { SchemeElement } from './scheme-element';
10
+
11
+ export class SchemeParser {
12
+ public parsedScheme: SchemeParsed;
13
+
14
+ constructor(
15
+ public scheme: SchemeInput,
16
+ public store: JabronioStore = new JabronioStore({}),
17
+ ) {
18
+ this.parsedScheme = this.parseScheme();
19
+ }
20
+
21
+ static parse(...args: ConstructorParameters<typeof SchemeParser>): {
22
+ scheme: SchemeParsed;
23
+ store: JabronioStore;
24
+ } {
25
+ const { parsedScheme, store } = new SchemeParser(...args);
26
+ // console.log('parsed scheme', parsedScheme);
27
+ // console.log('parsed store', JSON.parse(JSON.stringify(store)));
28
+ return { scheme: parsedScheme, store };
29
+ }
30
+
31
+ parseSchemeElement(schemeElement: SchemeElement) {
32
+ this.parseStatePropsFromModel(schemeElement);
33
+ this.parseStatePropsFromExpressions(schemeElement.text);
34
+ this.parseStatePropsFromExpressions(schemeElement.vif);
35
+ }
36
+
37
+ parseStatePropsFromModel(schemeElement: SchemeElement) {
38
+ const { name, value } = schemeElement;
39
+ if (
40
+ name === undefined ||
41
+ value === undefined ||
42
+ typeof value === 'function'
43
+ )
44
+ return;
45
+ this.store.add(name, value);
46
+ schemeElement.value = this.store.state[name];
47
+ }
48
+
49
+ parseStatePropsFromExpressions(expr?: string) {
50
+ if (!expr) return;
51
+ expr.match(/state\.\$?\w+/g)?.forEach((name) => {
52
+ const stateProp = name.replace('state.', '');
53
+ this.store.add(stateProp, '', undefined, false);
54
+ });
55
+ }
56
+
57
+ parseScheme() {
58
+ const parsedSchemeGroups: SchemeGroup<RawSchemeElement>[] = this.scheme.map(
59
+ (schemeSection: Partial<SchemeSection<RawSchemeElement>>, i) => {
60
+ const emptySchemeSection: SchemeGroup<RawSchemeElement> = {
61
+ content: [],
62
+ collapsed: false,
63
+ title: '',
64
+ id: `section ${i}`,
65
+ };
66
+
67
+ if (!schemeSection.content) {
68
+ this.store.add(emptySchemeSection.id, emptySchemeSection.collapsed);
69
+ return emptySchemeSection;
70
+ } else {
71
+ const mergedSchemeSection = {
72
+ ...emptySchemeSection,
73
+ ...schemeSection,
74
+ };
75
+ if (mergedSchemeSection.title.length > 0) {
76
+ mergedSchemeSection.id = mergedSchemeSection.title;
77
+ }
78
+ this.store.add(emptySchemeSection.id, emptySchemeSection.collapsed);
79
+ return mergedSchemeSection;
80
+ }
81
+ },
82
+ );
83
+
84
+ const parsedScheme: SchemeParsed = parsedSchemeGroups.map(
85
+ (schemeGroup: SchemeGroup<RawSchemeElement>) => {
86
+ const { content, ...rest } = schemeGroup;
87
+ const newContent = content.map(
88
+ (rawSchemeElement: RawSchemeElement) =>
89
+ new SchemeElement(rawSchemeElement),
90
+ );
91
+ return { content: newContent, ...rest } as SchemeGroup<SchemeElement>;
92
+ },
93
+ );
94
+
95
+ parsedScheme.forEach((schemeGroup) => {
96
+ schemeGroup.content.forEach((c) => {
97
+ this.parseSchemeElement(c);
98
+ });
99
+ });
100
+
101
+ return parsedScheme;
102
+ }
103
+ }
@@ -0,0 +1,93 @@
1
+ import type {
2
+ HTMLInputType,
3
+ HTMLTag,
4
+ HTMLTagOrInputType,
5
+ Primitive,
6
+ RawSchemeElement,
7
+ } from '../types';
8
+ import { propsDifference, uuidv4 } from '../utils';
9
+
10
+ export class SchemeElement {
11
+ public name?: string;
12
+ public value?: Primitive | (() => void);
13
+ public watch?: string;
14
+ public step?: string;
15
+ public min?: string;
16
+ public max?: string;
17
+ public vif?: string;
18
+ public text?: string;
19
+ public type: HTMLTagOrInputType = 'div';
20
+ public label?: string;
21
+ public placeholder?: string;
22
+ public id: string;
23
+
24
+ constructor(schemeElement: RawSchemeElement) {
25
+ const { d2 } = propsDifference(this, schemeElement);
26
+ Object.assign(this, schemeElement);
27
+ this.parseModel(d2);
28
+ this.parseType();
29
+ this.parseLabel();
30
+ this.id = this.name || uuidv4();
31
+ }
32
+
33
+ private parseType() {
34
+ if (this.type !== 'div') return;
35
+ if (this.value !== undefined) {
36
+ let parsedType: string = typeof this.value;
37
+ if (parsedType === 'function') {
38
+ parsedType = 'button';
39
+ } else if (parsedType === 'string') {
40
+ parsedType = 'text';
41
+ } else if (parsedType === 'number') {
42
+ parsedType = 'number';
43
+ this.parseNumber();
44
+ } else if (parsedType === 'boolean') {
45
+ parsedType = 'checkbox';
46
+ }
47
+ this.type = parsedType as HTMLInputType;
48
+ } else if (this.text) {
49
+ this.type = 'span';
50
+ }
51
+ }
52
+
53
+ private parseNumber() {
54
+ if (this.min || this.max || this.step) return;
55
+ this.min = '0';
56
+ this.step = '10';
57
+ }
58
+
59
+ private parseLabel() {
60
+ if (
61
+ this.label !== undefined ||
62
+ this.type === 'button'
63
+ )
64
+ return;
65
+ this.label = this.name;
66
+ }
67
+
68
+ private parseModel(differenceKeys: string[]) {
69
+ if (this.name && this.value) return;
70
+ const name = differenceKeys[0];
71
+ if (name) {
72
+ this.name = name;
73
+ this.value = this[name] as Primitive | (() => void);
74
+ delete this[name];
75
+ }
76
+ }
77
+
78
+ get isInput() {
79
+ return /checkbox|text|number/.test(this.type);
80
+ }
81
+
82
+ get htmlTag(): HTMLTag {
83
+ return this.isInput ? 'input' : (this.type as HTMLTag);
84
+ }
85
+
86
+ get inputType(): HTMLInputType {
87
+ return this.isInput ? (this.type as HTMLInputType) : '';
88
+ }
89
+
90
+ get callback(): (() => void) | undefined {
91
+ return this.htmlTag === 'button' ? (this.value as () => void) : undefined;
92
+ }
93
+ }
@@ -1,38 +1,9 @@
1
- import type { StateOptions } from "./types";
1
+ import type { StoreStateOptions } from '../types';
2
2
 
3
- export const stateOptions = {
4
- EXCLUDE: {
5
- filterExclude: { value: false, persistent: true, watch: true },
6
- filterExcludeWords: { value: "", persistent: true, watch: "filterExclude" },
7
- },
8
- INCLUDE: {
9
- filterInclude: { value: false, persistent: true, watch: true },
10
- filterIncludeWords: { value: "", persistent: true, watch: "filterInclude" },
11
- },
12
- MISC: {
13
- infiniteScrollEnabled: { value: true, persistent: true, watch: true },
14
- uiEnabled: { value: true, persistent: true, watch: true }
15
- },
16
- DURATION_FILTER: {
17
- filterDuration: { value: false, persistent: true, watch: true },
18
- filterDurationFrom: { value: 0, type: 'number', persistent: true, watch: 'filterDuration' },
19
- filterDurationTo: { value: 600, type: 'number', persistent: true, watch: 'filterDuration' }
20
- },
21
- PRIVACY_FILTER: {
22
- filterPrivate: { value: false, persistent: true, watch: true },
23
- filterPublic: { value: false, persistent: true, watch: true }
24
- },
25
- HD_FILTER: {
26
- filterHD: { value: false, persistent: true, watch: true }
27
- },
28
- PAGINATION: {
29
- pagIndexLast: { value: 1, persistent: false, watch: true },
30
- pagIndexCur: { value: 1, persistent: false, watch: true }
31
- }
32
- }
33
-
34
- export const defaultStateInclExclMiscPagination: StateOptions = Object.assign({}, stateOptions.EXCLUDE, stateOptions.INCLUDE, stateOptions.MISC, stateOptions.PAGINATION);
35
- export const defaultStateWithDuration: StateOptions = Object.assign({}, defaultStateInclExclMiscPagination, stateOptions.DURATION_FILTER);
36
- export const defaultStateWithDurationAndHD: StateOptions = Object.assign({}, defaultStateWithDuration, stateOptions.HD_FILTER);
37
- export const defaultStateWithDurationAndPrivacy: StateOptions = Object.assign({}, defaultStateWithDuration, stateOptions.PRIVACY_FILTER);
38
- export const defaultStateWithDurationAndPrivacyAndHD: StateOptions = Object.assign({}, defaultStateWithDurationAndPrivacy, stateOptions.HD_FILTER);
3
+ export const StoreStateDefault: StoreStateOptions = {
4
+ uiEnabled: true,
5
+ hidden: false,
6
+ darkmode: true,
7
+ $paginationLast: 1,
8
+ $paginationOffset: 1,
9
+ };
@@ -0,0 +1,63 @@
1
+ import { parseIntegerOr } from 'billy-herrington-utils';
2
+ import { watch } from 'vue';
3
+ import type {
4
+ Callback,
5
+ Primitive,
6
+ StoreState,
7
+ StoreStateOptions,
8
+ StoreStateRaw,
9
+ } from '../types';
10
+ import { StoreStateDefault } from './default-state';
11
+ import { PersistentState } from './persistent-state';
12
+
13
+ export class JabronioStore {
14
+ private callbacks: Callback<StoreStateRaw>[] = [];
15
+ public state: StoreState;
16
+
17
+ constructor(options?: StoreStateOptions) {
18
+ const storeOptions = Object.assign({}, StoreStateDefault, options);
19
+ this.state = new PersistentState({}).state;
20
+ this.parseState(storeOptions);
21
+ }
22
+
23
+ subscribe(callback: Callback<StoreStateRaw>) {
24
+ this.callbacks.push(callback);
25
+ }
26
+
27
+ notify(subject: StoreStateRaw) {
28
+ this.callbacks.forEach((cb) => {
29
+ cb(subject);
30
+ });
31
+ }
32
+
33
+ add(key: string, value: Primitive, watchKey?: string, safe?: boolean) {
34
+ this.state[key] =
35
+ key in this.state ? (this.state[key] as Primitive) : value;
36
+
37
+ watch(
38
+ () => this.state[key],
39
+ (a, b) => {
40
+ if (safe !== false) {
41
+ if (typeof value === 'number') {
42
+ this.state[key] = parseIntegerOr(a as string, b as number);
43
+ }
44
+ }
45
+ const subject = typeof watchKey === 'string' ? watchKey : key;
46
+ this.notify({ [subject]: this.state[subject] as Primitive });
47
+ },
48
+ { deep: true },
49
+ );
50
+
51
+ return this;
52
+ }
53
+
54
+ parseState(options: StoreStateOptions) {
55
+ Object.entries(options).forEach(([k, v]) => {
56
+ if (typeof v === 'object') {
57
+ this.add(k, v.value, v.watch);
58
+ } else {
59
+ this.add(k, v);
60
+ }
61
+ });
62
+ }
63
+ }
@@ -1,36 +1,64 @@
1
- import { type Reactive, reactive, watch } from 'vue'
2
- import type { RecordV } from './types';
1
+ import { type Reactive, reactive, type WatchStopHandle, watch } from 'vue';
2
+ import type { StoreStateRaw } from '../types';
3
+
4
+ const LOCAL_STORAGE_KEY = 'state_acephale';
3
5
 
4
6
  export class PersistentState {
5
- public state: Reactive<RecordV>;
7
+ public state: Reactive<StoreStateRaw>;
8
+ private watchStopHandler: WatchStopHandle;
6
9
 
7
- constructor(state_: RecordV, private key = "state_acephale") {
10
+ constructor(
11
+ storeStateRaw: StoreStateRaw,
12
+ private key = LOCAL_STORAGE_KEY,
13
+ ) {
8
14
  this.key = key;
9
- this.state = reactive(state_);
15
+ this.state = reactive(storeStateRaw);
10
16
  this.sync();
11
- this.watchPersistence();
17
+ this.watchStopHandler = this.watchPersistence();
18
+ }
19
+
20
+ dispose() {
21
+ this.watchStopHandler();
22
+ window.removeEventListener('focus', this.setFromLocalStorage);
23
+ document.removeEventListener('visibilitychange', this.setFromLocalStorage);
12
24
  }
13
25
 
14
26
  sync() {
15
- this.trySetFromLocalStorage();
16
- window.addEventListener('focus', this.trySetFromLocalStorage);
27
+ this.setFromLocalStorage();
28
+ window.addEventListener('focus', this.setFromLocalStorage);
29
+ document.addEventListener('visibilitychange', this.setFromLocalStorage);
17
30
  }
18
31
 
19
32
  watchPersistence() {
20
- watch(this.state, (value) => {
21
- this.saveToLocalStorage(this.key, value);
22
- });
33
+ return watch(
34
+ this.state,
35
+ () => {
36
+ this.saveToLocalStorage();
37
+ },
38
+ { immediate: false, deep: true },
39
+ );
23
40
  }
24
41
 
25
- saveToLocalStorage(key: string, value: RecordV) {
26
- localStorage.setItem(key, JSON.stringify(value));
42
+ get persistentOnly() {
43
+ const persistentKeys = Object.keys(this.state).filter(
44
+ (k) => !k.startsWith('$'),
45
+ );
46
+ const persistentOnly = Object.assign(
47
+ {},
48
+ ...persistentKeys.map((k) => ({ [k]: this.state[k] })),
49
+ );
50
+ return persistentOnly;
27
51
  }
28
52
 
29
- trySetFromLocalStorage = () => {
53
+ saveToLocalStorage() {
54
+ localStorage.setItem(this.key, JSON.stringify(this.persistentOnly));
55
+ }
56
+
57
+ setFromLocalStorage = () => {
30
58
  const localStorageValue = localStorage.getItem(this.key);
31
59
  if (localStorageValue !== null) {
32
- const parsedState = JSON.parse(localStorageValue) as RecordV;
60
+ const parsedState = JSON.parse(localStorageValue) as StoreStateRaw;
33
61
  Object.assign(this.state, parsedState);
34
62
  }
35
- }
36
- }
63
+ };
64
+ }
@@ -0,0 +1,30 @@
1
+ @import "tailwindcss/theme";
2
+
3
+ @layer base, components, utilities;
4
+
5
+ @layer base {
6
+ .taper-class {
7
+ @import "tailwindcss/preflight";
8
+
9
+ &, & *, & ::after, & ::before {
10
+ all: revert-layer;
11
+ }
12
+ }
13
+ }
14
+
15
+ @layer utilities {
16
+ .taper-class {
17
+ @import "tailwindcss/utilities";
18
+ }
19
+ }
20
+
21
+ @custom-variant dark (&:where([data-theme=dark], [data-theme=dark] *));
22
+
23
+ @layer components {
24
+ .tw-input-colors {
25
+ @apply border-black focus:outline-none focus:bg-yellow-50;
26
+ @apply dark:text-zinc-300 dark:bg-zinc-700 dark:focus:outline-gray-600
27
+ dark:hover:bg-zinc-600 dark:focus:bg-zinc-700;
28
+
29
+ }
30
+ }
@@ -1,52 +1,64 @@
1
- import { defaultStateWithDurationAndPrivacyAndHD } from "../store/default-state";
2
- import { JabroniOutfitStore } from "../store/store";
3
- import type { StateOptions } from "../store/types";
4
- import { JabroniOutfitUI } from "../ui";
5
- import { defaultSchemeWithPrivacyFilterWithHDwithSort } from "../ui/default-scheme";
6
- import type { Scheme } from "../ui/types";
7
-
8
- const example1 = () => {
9
- // biome-ignore lint/suspicious/noExplicitAny: <explanation>
10
- (defaultSchemeWithPrivacyFilterWithHDwithSort as any).privacyFilter.push(
11
- { type: "button", innerText: "check access 🔓", callback: () => { } });
12
-
13
- const store = new JabroniOutfitStore(defaultStateWithDurationAndPrivacyAndHD);
14
-
15
- new JabroniOutfitUI(store, defaultSchemeWithPrivacyFilterWithHDwithSort);
16
-
17
- store.subscribe((subj) => {
18
- const satisfy = /filter/gi.test(Object.keys(subj)[0]);
19
- console.log({ ...subj, satisfy });
20
- });
21
- }
22
-
23
- example1();
1
+ import { JabronioGUI } from '../app';
2
+ import { DefaultScheme, setupScheme } from '../scheme/default-scheme';
3
+ import { JabronioStore } from '../store';
4
+ import type { SchemeInput, StoreStateOptions } from '../types';
24
5
 
25
6
  const example2 = () => {
26
- const customState: StateOptions = {
27
- gradientColor1: { value: "red", persistent: false, watch: true, type: "string" },
28
- gradientColor2: { value: "coral", persistent: false, watch: true, type: "string" },
29
- gradientColor3: { value: "orange", persistent: false, watch: true, type: "string" },
30
- gradientEnabled: { value: true, persistent: false, watch: true, type: "boolean" },
31
- uiEnabled: { value: true, persistent: true, watch: true, type: "boolean" }
32
- }
7
+ const customState: StoreStateOptions = {
8
+ uiEnabled: true,
9
+ hidden: false,
10
+ };
33
11
 
34
- const store = new JabroniOutfitStore(customState);
12
+ const store = new JabronioStore(customState);
35
13
 
36
- const customScheme: Scheme = {
37
- gradientColor1: [{ type: "text", model: "localState.gradientColor1", placeholder: "color", labelBefore: "color1" }],
38
- gradientColor2: [{ type: "text", model: "localState.gradientColor2", placeholder: "color", labelBefore: "color2" }],
39
- gradientColor3: [{ type: "text", model: "localState.gradientColor3", placeholder: "color", labelBefore: "color3" }],
40
- gradientEnabled: [{ type: "checkbox", model: "localState.gradientEnabled", labelBefore: "gradient enabled" }],
41
- };
14
+ const scheme: SchemeInput = setupScheme(
15
+ DefaultScheme.map((t) => t.title).filter(Boolean),
16
+ // [],
17
+ [
18
+ {
19
+ title: 'Colors',
20
+ collapsed: true,
21
+ content: [
22
+ {
23
+ $color1: 'coral',
24
+ },
25
+ {
26
+ color2: 'crimson',
27
+ },
28
+ {
29
+ $color3: 'tomato',
30
+ },
31
+ {
32
+ size: 100,
33
+ type: 'range',
34
+ max: '500',
35
+ min: '0',
36
+ },
37
+ {
38
+ gradientEnabled: true,
39
+ label: 'gradient enabled',
40
+ },
41
+ {
42
+ reset: () => {
43
+ store.state.$color1 = 'darkslateblue';
44
+ store.state.color2 = 'maroon';
45
+ store.state.$color3 = 'darksalmon';
46
+ },
47
+ },
48
+ ],
49
+ },
50
+ ],
51
+ );
42
52
 
43
- new JabroniOutfitUI(store, customScheme);
53
+ new JabronioGUI(scheme, store);
44
54
 
45
55
  function drawGradient() {
46
- // biome-ignore lint/suspicious/noExplicitAny: <explanation>
47
- const { gradientColor1, gradientColor2, gradientColor3, gradientEnabled } = store.localState as any;
48
- if (!gradientEnabled) { document.body.style.background = 'blue'; return; }
49
- document.body.style.background = `radial-gradient(${gradientColor1}, ${gradientColor2}, ${gradientColor3})`;
56
+ const { $color1, color2, $color3, gradientEnabled, size } = store.state;
57
+ if (!gradientEnabled) {
58
+ document.body.style.background = '#000';
59
+ return;
60
+ }
61
+ document.body.style.background = `repeating-radial-gradient(${$color1}, ${color2}, ${$color3} ${size}%)`;
50
62
  }
51
63
 
52
64
  drawGradient();
@@ -54,6 +66,6 @@ const example2 = () => {
54
66
  store.subscribe(() => {
55
67
  drawGradient();
56
68
  });
57
- }
69
+ };
58
70
 
59
- example2();
71
+ example2();