@dodlhuat/basix 1.3.3 → 1.3.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +78 -12
- package/css/badge.scss +8 -0
- package/css/button.scss +61 -15
- package/css/chips.scss +10 -0
- package/css/colors.scss +4 -0
- package/css/docs.scss +0 -4
- package/css/dropdown.scss +14 -0
- package/css/modal.scss +21 -0
- package/css/sidebar-nav.scss +25 -0
- package/css/style.css +224 -21
- package/css/style.css.map +1 -1
- package/css/style.min.css +1 -1
- package/css/style.min.css.map +1 -1
- package/css/tabs.scss +49 -0
- package/css/typography.scss +36 -7
- package/js/dropdown.d.ts +1 -0
- package/js/dropdown.js +11 -0
- package/js/editor.d.ts +6 -1
- package/js/editor.js +48 -31
- package/js/gallery.d.ts +2 -0
- package/js/gallery.js +22 -2
- package/js/modal.js +1 -1
- package/js/sidebar-nav.d.ts +11 -1
- package/js/sidebar-nav.js +40 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Basix 1.3.
|
|
1
|
+
# Basix 1.3.5
|
|
2
2
|
|
|
3
3
|
Basix is intended as a starter for the rapid development of a design. Each design element can be added individually to
|
|
4
4
|
include only the data required. It is using plain javascript / typescript and therefore is not dependent on any plugin.
|
|
@@ -830,25 +830,91 @@ new CodeViewer('#output', '.card { padding: 1rem; }', 'css');
|
|
|
830
830
|
|
|
831
831
|
### Editor
|
|
832
832
|
|
|
833
|
-
The Editor component provides a contenteditable rich-text editing area with undo/redo, word count, and an optional side panel showing the raw HTML source and a live preview.
|
|
833
|
+
The Editor component provides a contenteditable rich-text editing area with undo/redo, word count, and an optional side panel showing the raw HTML source and a live preview. Internal elements are located by `data-editor` attributes scoped to a `root` container — no globally unique IDs required, which makes multiple editors on the same page possible.
|
|
834
834
|
|
|
835
835
|
``` html
|
|
836
|
-
<div
|
|
837
|
-
|
|
838
|
-
<
|
|
839
|
-
<
|
|
840
|
-
<
|
|
841
|
-
<
|
|
836
|
+
<div class="editor" id="my-editor">
|
|
837
|
+
<div class="editor-toolbar">
|
|
838
|
+
<button data-editor-action="undo" title="Undo">↩</button>
|
|
839
|
+
<button data-editor-action="redo" title="Redo">↪</button>
|
|
840
|
+
<button data-cmd="bold">B</button>
|
|
841
|
+
<button data-cmd="italic">I</button>
|
|
842
|
+
<button data-editor-action="link">Link</button>
|
|
843
|
+
<!-- … -->
|
|
844
|
+
</div>
|
|
845
|
+
<div class="editor-body">
|
|
846
|
+
<div class="editor-main">
|
|
847
|
+
<div data-editor="editable" class="editable" contenteditable="true"></div>
|
|
848
|
+
</div>
|
|
849
|
+
<!-- Full mode: add side panel with code + preview -->
|
|
850
|
+
<div data-editor="side-panel" class="editor-side">
|
|
851
|
+
<div class="side-tabs">
|
|
852
|
+
<button class="side-tab active" data-tab="code-panel">HTML</button>
|
|
853
|
+
<button class="side-tab" data-tab="preview-panel">Preview</button>
|
|
854
|
+
</div>
|
|
855
|
+
<div class="side-panels">
|
|
856
|
+
<div class="side-panel active" data-editor="code-panel">
|
|
857
|
+
<textarea data-editor="code"></textarea>
|
|
858
|
+
</div>
|
|
859
|
+
<div class="side-panel" data-editor="preview-panel">
|
|
860
|
+
<div data-editor="preview" class="preview-content"></div>
|
|
861
|
+
</div>
|
|
862
|
+
</div>
|
|
863
|
+
</div>
|
|
864
|
+
</div>
|
|
865
|
+
<div class="editor-footer">
|
|
866
|
+
<span data-editor="wordcount">0 words</span>
|
|
867
|
+
</div>
|
|
868
|
+
</div>
|
|
842
869
|
```
|
|
843
870
|
|
|
844
871
|
``` js
|
|
845
|
-
//
|
|
846
|
-
new Editor();
|
|
872
|
+
// Single editor
|
|
873
|
+
new Editor({ root: '#my-editor' });
|
|
874
|
+
|
|
875
|
+
// Simple mode — only requires [data-editor="editable"], hides the side panel
|
|
876
|
+
new Editor({ root: '#my-editor', simple: true });
|
|
877
|
+
|
|
878
|
+
// Multiple editors on the same page
|
|
879
|
+
const editor1 = new Editor({ root: '#editor-1' });
|
|
880
|
+
const editor2 = new Editor({ root: '#editor-2' });
|
|
847
881
|
|
|
848
|
-
|
|
849
|
-
new Editor({ simple: true });
|
|
882
|
+
editor1.destroy();
|
|
850
883
|
```
|
|
851
884
|
|
|
885
|
+
#### Options
|
|
886
|
+
|
|
887
|
+
| Option | Type | Default | Description |
|
|
888
|
+
|---|---|---|---|
|
|
889
|
+
| `root` | string \| HTMLElement | `document.body` | Root container. Required when multiple editors coexist on the same page. |
|
|
890
|
+
| `simple` | boolean | `false` | Simple mode requires only `[data-editor="editable"]`. Full mode additionally requires `code`, `preview`, `side-panel`, `code-panel`, and `preview-panel` elements. |
|
|
891
|
+
|
|
892
|
+
#### `data-editor` elements
|
|
893
|
+
|
|
894
|
+
| Value | Element | Required |
|
|
895
|
+
|---|---|---|
|
|
896
|
+
| `editable` | `contenteditable` div — the writing area | always |
|
|
897
|
+
| `code` | `<textarea>` — HTML source view | full mode |
|
|
898
|
+
| `preview` | `<div>` — live preview | full mode |
|
|
899
|
+
| `side-panel` | Side panel container | full mode |
|
|
900
|
+
| `code-panel` | Code tab panel (matches `data-tab="code-panel"`) | full mode |
|
|
901
|
+
| `preview-panel` | Preview tab panel | full mode |
|
|
902
|
+
| `wordcount` | Word count display | optional |
|
|
903
|
+
| `image-file` | `<input type="file">` for image insertion | optional |
|
|
904
|
+
|
|
905
|
+
#### `data-editor-action` buttons
|
|
906
|
+
|
|
907
|
+
| Value | Description |
|
|
908
|
+
|---|---|
|
|
909
|
+
| `undo` | Triggers undo |
|
|
910
|
+
| `redo` | Triggers redo |
|
|
911
|
+
| `link` | Opens URL prompt for link insertion |
|
|
912
|
+
| `image` | Triggers the image file picker |
|
|
913
|
+
| `save` | Downloads content as an HTML file (Ctrl+S) |
|
|
914
|
+
| `clear` | Clears all content |
|
|
915
|
+
| `clean` | Strips formatting from the current selection |
|
|
916
|
+
| `toggle-code` | Shows / hides the HTML side panel |
|
|
917
|
+
|
|
852
918
|
### Custom Scrollbar
|
|
853
919
|
|
|
854
920
|
The Scrollbar component creates custom-styled scrollbars. Supports pointer/touch dragging, track clicking, and automatic thumb sizing. Can be used with any class.
|
package/css/badge.scss
CHANGED
|
@@ -97,3 +97,11 @@
|
|
|
97
97
|
&.badge-error { background: var(--error); }
|
|
98
98
|
}
|
|
99
99
|
}
|
|
100
|
+
|
|
101
|
+
[data-theme="dark"] {
|
|
102
|
+
.badge-solid {
|
|
103
|
+
&.badge-success { color: var(--background); }
|
|
104
|
+
&.badge-warning { color: var(--background); }
|
|
105
|
+
&.badge-error { color: var(--background); }
|
|
106
|
+
}
|
|
107
|
+
}
|
package/css/button.scss
CHANGED
|
@@ -60,7 +60,7 @@ button,
|
|
|
60
60
|
}
|
|
61
61
|
|
|
62
62
|
&.active {
|
|
63
|
-
background: var(--
|
|
63
|
+
background: var(--accent-color-tint);
|
|
64
64
|
color: var(--accent-color);
|
|
65
65
|
}
|
|
66
66
|
|
|
@@ -172,29 +172,75 @@ button.button-error {
|
|
|
172
172
|
|
|
173
173
|
.button-success,
|
|
174
174
|
button.button-success {
|
|
175
|
-
|
|
175
|
+
color: var(--background);
|
|
176
|
+
&:hover:not(:disabled) { background: color-mix(in srgb, var(--success) 82%, white); }
|
|
177
|
+
&:active:not(:disabled) { background: color-mix(in srgb, var(--success) 70%, white); }
|
|
178
|
+
&.is-loading::after { color: var(--background); }
|
|
176
179
|
}
|
|
177
180
|
|
|
178
181
|
.button-warning,
|
|
179
182
|
button.button-warning {
|
|
180
|
-
|
|
183
|
+
color: var(--background);
|
|
184
|
+
&:hover:not(:disabled) { background: color-mix(in srgb, var(--warning) 82%, white); }
|
|
185
|
+
&:active:not(:disabled) { background: color-mix(in srgb, var(--warning) 70%, white); }
|
|
186
|
+
&.is-loading::after { color: var(--background); }
|
|
181
187
|
}
|
|
182
188
|
|
|
183
189
|
.button-error,
|
|
184
190
|
button.button-error {
|
|
185
|
-
|
|
191
|
+
color: var(--background);
|
|
192
|
+
&:hover:not(:disabled) { background: color-mix(in srgb, var(--error) 82%, white); }
|
|
193
|
+
&:active:not(:disabled) { background: color-mix(in srgb, var(--error) 70%, white); }
|
|
194
|
+
&.is-loading::after { color: var(--background); }
|
|
186
195
|
}
|
|
187
196
|
|
|
188
|
-
.button-primary,
|
|
189
|
-
button.button-primary
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
197
|
+
.button-primary.is-loading::after,
|
|
198
|
+
button.button-primary.is-loading::after {
|
|
199
|
+
color: var(--primary-text);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// Size variants
|
|
204
|
+
.button-sm,
|
|
205
|
+
button.button-sm {
|
|
206
|
+
padding: calc($spacing * 0.35) calc($spacing * 0.75);
|
|
207
|
+
font-size: 0.8125rem;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
.button-lg,
|
|
211
|
+
button.button-lg {
|
|
212
|
+
padding: calc($spacing * 0.8) calc($spacing * 1.75);
|
|
213
|
+
font-size: 1.0625rem;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// Outline variant
|
|
217
|
+
.button-outline,
|
|
218
|
+
button.button-outline {
|
|
219
|
+
background: transparent;
|
|
220
|
+
border: 1px solid var(--divider);
|
|
221
|
+
color: var(--primary-text);
|
|
222
|
+
|
|
223
|
+
&:hover:not(:disabled) {
|
|
224
|
+
background: var(--hover);
|
|
225
|
+
border-color: color-mix(in srgb, var(--divider) 50%, var(--primary-text));
|
|
199
226
|
}
|
|
227
|
+
|
|
228
|
+
&:active:not(:disabled) {
|
|
229
|
+
background: var(--secondary-background);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
// Icon-only button — square, equal padding
|
|
234
|
+
.button-icon,
|
|
235
|
+
button.button-icon {
|
|
236
|
+
padding: calc($spacing * 0.5);
|
|
237
|
+
width: 2.25rem;
|
|
238
|
+
height: 2.25rem;
|
|
239
|
+
flex-shrink: 0;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// Pill variant
|
|
243
|
+
.button-pill,
|
|
244
|
+
button.button-pill {
|
|
245
|
+
border-radius: $radius-xl;
|
|
200
246
|
}
|
package/css/chips.scss
CHANGED
|
@@ -39,6 +39,16 @@
|
|
|
39
39
|
outline: none;
|
|
40
40
|
@include focus-glow();
|
|
41
41
|
}
|
|
42
|
+
|
|
43
|
+
&.selected {
|
|
44
|
+
background: color-mix(in srgb, var(--accent-color) 12%, var(--background));
|
|
45
|
+
color: var(--accent-color);
|
|
46
|
+
border-color: color-mix(in srgb, var(--accent-color) 25%, transparent);
|
|
47
|
+
|
|
48
|
+
&:hover {
|
|
49
|
+
background: color-mix(in srgb, var(--accent-color) 18%, var(--background));
|
|
50
|
+
}
|
|
51
|
+
}
|
|
42
52
|
}
|
|
43
53
|
|
|
44
54
|
&.closeable {
|
package/css/colors.scss
CHANGED
package/css/docs.scss
CHANGED
package/css/dropdown.scss
CHANGED
|
@@ -14,6 +14,20 @@
|
|
|
14
14
|
}
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
+
&.drop-up {
|
|
18
|
+
> .dropdown-menu {
|
|
19
|
+
top: auto;
|
|
20
|
+
bottom: 100%;
|
|
21
|
+
margin-top: 0;
|
|
22
|
+
margin-bottom: 6px;
|
|
23
|
+
transform: translateY(8px);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
&.active > .dropdown-menu {
|
|
27
|
+
transform: translateY(0);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
17
31
|
.dropdown-menu {
|
|
18
32
|
position: absolute;
|
|
19
33
|
top: 100%;
|
package/css/modal.scss
CHANGED
|
@@ -88,6 +88,27 @@
|
|
|
88
88
|
}
|
|
89
89
|
}
|
|
90
90
|
|
|
91
|
+
// Coloured variants — border echoes the type colour, close icon and header text go white
|
|
92
|
+
.modal-success { border-color: color-mix(in srgb, var(--success) 35%, transparent); }
|
|
93
|
+
.modal-error { border-color: color-mix(in srgb, var(--error) 35%, transparent); }
|
|
94
|
+
.modal-warning { border-color: color-mix(in srgb, var(--warning) 35%, transparent); }
|
|
95
|
+
.modal-info { border-color: color-mix(in srgb, var(--accent-color) 35%, transparent); }
|
|
96
|
+
|
|
97
|
+
.modal-success,
|
|
98
|
+
.modal-error,
|
|
99
|
+
.modal-warning,
|
|
100
|
+
.modal-info {
|
|
101
|
+
.close {
|
|
102
|
+
color: rgba(255, 255, 255, 0.8);
|
|
103
|
+
&:hover { color: #fff; }
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
.header {
|
|
107
|
+
color: #fff;
|
|
108
|
+
border-bottom-color: rgba(255, 255, 255, 0.2);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
91
112
|
@media screen and (max-width: 768px) {
|
|
92
113
|
.modal-wrapper.is-visible .modal {
|
|
93
114
|
transform: translateY(0);
|
package/css/sidebar-nav.scss
CHANGED
|
@@ -57,6 +57,10 @@
|
|
|
57
57
|
svg { display: block; }
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
+
.sidebar-close {
|
|
61
|
+
display: none;
|
|
62
|
+
}
|
|
63
|
+
|
|
60
64
|
@media (max-width: 768px) {
|
|
61
65
|
.sidebar-toggle {
|
|
62
66
|
display: flex;
|
|
@@ -77,4 +81,25 @@
|
|
|
77
81
|
.sidebar-main {
|
|
78
82
|
margin-left: 0;
|
|
79
83
|
}
|
|
84
|
+
|
|
85
|
+
.sidebar-close {
|
|
86
|
+
display: flex;
|
|
87
|
+
align-items: center;
|
|
88
|
+
justify-content: center;
|
|
89
|
+
position: absolute;
|
|
90
|
+
bottom: 1rem;
|
|
91
|
+
left: 50%;
|
|
92
|
+
transform: translateX(-50%);
|
|
93
|
+
background: var(--secondary-background);
|
|
94
|
+
border: none;
|
|
95
|
+
border-radius: $border-radius;
|
|
96
|
+
padding: 0.5rem 1.25rem;
|
|
97
|
+
cursor: pointer;
|
|
98
|
+
color: var(--primary-text);
|
|
99
|
+
gap: 0.4rem;
|
|
100
|
+
font-size: 0.875rem;
|
|
101
|
+
white-space: nowrap;
|
|
102
|
+
|
|
103
|
+
&:hover { background: var(--divider); }
|
|
104
|
+
}
|
|
80
105
|
}
|