domma-cms 0.9.0 → 0.9.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/admin/js/templates/block-editor.html +163 -163
- package/admin/js/templates/form-editor.html +245 -245
- package/admin/js/views/action-editor.js +1 -1
- package/admin/js/views/block-editor.js +8 -8
- package/admin/js/views/collection-editor.js +4 -4
- package/admin/js/views/collections.js +1 -1
- package/admin/js/views/form-editor.js +7 -7
- package/admin/js/views/forms.js +1 -1
- package/admin/js/views/navigation.js +14 -14
- package/admin/js/views/page-editor.js +35 -35
- package/admin/js/views/pages.js +5 -5
- package/admin/js/views/plugins.js +19 -10
- package/admin/js/views/view-editor.js +1 -1
- package/config/plugins.json +35 -0
- package/package.json +1 -1
- package/plugins/docs/data/documents/57e003f0-68f2-47dc-9c36-ed4b10ed3deb.json +4 -4
- package/plugins/docs/data/folders.json +3 -3
- package/plugins/docs/data/versions/57e003f0-68f2-47dc-9c36-ed4b10ed3deb/1.json +5 -0
- package/plugins/garage/admin/templates/garage.html +30 -0
- package/plugins/garage/admin/views/garage.js +62 -1
- package/plugins/garage/plugin.json +1 -1
- package/plugins/notes/admin/templates/notes.html +2 -11
- package/plugins/notes/admin/views/notes.js +107 -129
- package/plugins/notes/collections/user-notes/schema.json +2 -1
- package/plugins/notes/plugin.json +1 -1
- package/plugins/site-search/admin/templates/site-search.html +174 -46
- package/plugins/site-search/admin/views/site-search.js +72 -1
- package/plugins/site-search/config.js +6 -1
- package/plugins/site-search/plugin.json +1 -1
- package/plugins/site-search/public/inject-head.html +1 -1
- package/plugins/site-search/public/search.css +1 -1
- package/plugins/site-search/public/search.js +1 -1
- package/plugins/todo/admin/templates/todo.html +2 -8
- package/plugins/todo/admin/views/todo.js +122 -106
- package/plugins/todo/collections/todos/schema.json +2 -1
- package/plugins/todo/plugin.json +1 -1
- package/server/routes/api/media.js +127 -118
- package/server/routes/api/plugins.js +15 -4
- package/server/server.js +288 -285
- package/server/services/blocks.js +6 -3
- package/server/services/collections.js +17 -10
- package/server/services/plugins.js +77 -67
- package/server/services/renderer.js +3 -3
- package/plugins/docs/data/documents/452f49b7-9c93-4a67-874d-27f882891ad2.json +0 -11
|
@@ -7,61 +7,189 @@
|
|
|
7
7
|
</div>
|
|
8
8
|
</div>
|
|
9
9
|
|
|
10
|
-
<div
|
|
11
|
-
<div class="
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
<
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
10
|
+
<div id="ss-settings-tabs" class="tabs">
|
|
11
|
+
<div class="tab-list">
|
|
12
|
+
<button class="tab-item active">Settings</button>
|
|
13
|
+
<button class="tab-item">Trigger & Position</button>
|
|
14
|
+
<button class="tab-item">How it works</button>
|
|
15
|
+
</div>
|
|
16
|
+
<div class="tab-content">
|
|
17
|
+
|
|
18
|
+
<!-- Settings Tab -->
|
|
19
|
+
<div class="tab-panel active" id="tab-search-settings">
|
|
20
|
+
<div class="card mb-4" style="margin-top:1rem;">
|
|
21
|
+
<div class="card-body">
|
|
22
|
+
|
|
23
|
+
<div class="row mb-3">
|
|
24
|
+
<div class="col">
|
|
25
|
+
<label class="form-label">Search placeholder text</label>
|
|
26
|
+
<input id="field-placeholder" type="text" class="form-input" placeholder="Search pages...">
|
|
27
|
+
<span class="form-hint">Displayed inside the search input when empty.</span>
|
|
28
|
+
</div>
|
|
29
|
+
</div>
|
|
30
|
+
|
|
31
|
+
<div class="row mb-3">
|
|
32
|
+
<div class="col">
|
|
33
|
+
<label class="form-check-label">
|
|
34
|
+
<input id="field-keyboard-shortcut" type="checkbox">
|
|
35
|
+
Enable keyboard shortcut (Ctrl+K / ⌘K)
|
|
36
|
+
</label>
|
|
37
|
+
<span class="form-hint">Allows visitors to open the search overlay using a keyboard shortcut.</span>
|
|
38
|
+
</div>
|
|
39
|
+
</div>
|
|
21
40
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
41
|
+
<div class="row mb-3">
|
|
42
|
+
<div class="col-6">
|
|
43
|
+
<label class="form-label">Max results</label>
|
|
44
|
+
<input id="field-max-results" type="number" class="form-input" min="1" max="50"
|
|
45
|
+
placeholder="10">
|
|
46
|
+
<span class="form-hint">Maximum number of results to return per search (1–50).</span>
|
|
47
|
+
</div>
|
|
48
|
+
<div class="col-6">
|
|
49
|
+
<label class="form-label">Minimum query length</label>
|
|
50
|
+
<input id="field-min-query-length" type="number" class="form-input" min="1" max="5"
|
|
51
|
+
placeholder="2">
|
|
52
|
+
<span class="form-hint">Minimum characters required before searching (1–5).</span>
|
|
53
|
+
</div>
|
|
54
|
+
</div>
|
|
55
|
+
|
|
56
|
+
<div class="row">
|
|
57
|
+
<div class="col-6">
|
|
58
|
+
<label class="form-label">Debounce delay (ms)</label>
|
|
59
|
+
<input id="field-debounce-ms" type="number" class="form-input" min="100" max="1000"
|
|
60
|
+
placeholder="300">
|
|
61
|
+
<span class="form-hint">Delay after typing stops before search fires (100–1000ms).</span>
|
|
62
|
+
</div>
|
|
63
|
+
</div>
|
|
64
|
+
|
|
65
|
+
</div>
|
|
29
66
|
</div>
|
|
30
67
|
</div>
|
|
31
68
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
<
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
69
|
+
<!-- Trigger & Position Tab -->
|
|
70
|
+
<div class="tab-panel" id="tab-trigger-position">
|
|
71
|
+
<div class="card mb-4" style="margin-top:1rem;">
|
|
72
|
+
<div class="card-body">
|
|
73
|
+
|
|
74
|
+
<div class="row mb-3">
|
|
75
|
+
<div class="col">
|
|
76
|
+
<label class="form-label">Display Mode</label>
|
|
77
|
+
<div id="ss-display-mode" style="display:flex;gap:8px;flex-wrap:wrap;">
|
|
78
|
+
<button type="button" class="btn ss-mode-btn" data-mode="navbar">
|
|
79
|
+
<span data-icon="menu" data-icon-size="14" style="margin-right:5px;"></span>Navbar
|
|
80
|
+
</button>
|
|
81
|
+
<button type="button" class="btn ss-mode-btn" data-mode="floating">
|
|
82
|
+
<span data-icon="search" data-icon-size="14" style="margin-right:5px;"></span>Floating
|
|
83
|
+
Button
|
|
84
|
+
</button>
|
|
85
|
+
</div>
|
|
86
|
+
<input type="hidden" id="field-display-mode" value="navbar">
|
|
87
|
+
<span class="form-hint">Navbar adds the icon to the site navigation. Floating button shows a fixed button on every page.</span>
|
|
88
|
+
</div>
|
|
89
|
+
</div>
|
|
90
|
+
|
|
91
|
+
<div id="ss-pos-section" style="display:none;">
|
|
92
|
+
|
|
93
|
+
<div class="row mb-3">
|
|
94
|
+
<div class="col">
|
|
95
|
+
<label class="form-check-label">
|
|
96
|
+
<input id="field-icon-only" type="checkbox" checked>
|
|
97
|
+
Icon only
|
|
98
|
+
</label>
|
|
99
|
+
<span class="form-hint">When unchecked, shows a "Search" label alongside the icon.</span>
|
|
100
|
+
</div>
|
|
101
|
+
</div>
|
|
102
|
+
|
|
103
|
+
<div class="row" style="align-items:flex-start;gap:0;">
|
|
104
|
+
|
|
105
|
+
<div class="col-auto" style="margin-right:1.5rem;margin-bottom:1rem;">
|
|
106
|
+
<label class="form-label" style="margin-bottom:.6rem;">Position</label>
|
|
107
|
+
<div id="ss-pos-grid"
|
|
108
|
+
style="display:grid;grid-template-columns:1fr 1fr;gap:2px;border:1px solid var(--border-color,rgba(255,255,255,.1));border-radius:10px;overflow:hidden;background:var(--border-color,rgba(255,255,255,.07));width:fit-content;">
|
|
109
|
+
|
|
110
|
+
<div class="ss-pos-btn" data-pos="top-left"
|
|
111
|
+
style="display:flex;flex-direction:column;align-items:flex-start;padding:.55rem .8rem;cursor:pointer;font-size:.78rem;color:var(--text-muted,#888);border-right:1px solid var(--border-color,rgba(255,255,255,.08));border-bottom:1px solid var(--border-color,rgba(255,255,255,.08));gap:.05rem;user-select:none;transition:background .15s,color .15s;min-width:84px;">
|
|
112
|
+
<span style="font-size:.6rem;opacity:.55;letter-spacing:.06em;text-transform:uppercase;line-height:1.2;">Top</span>
|
|
113
|
+
<span style="font-weight:600;">↖ Left</span>
|
|
114
|
+
</div>
|
|
115
|
+
<div class="ss-pos-btn" data-pos="top-right"
|
|
116
|
+
style="display:flex;flex-direction:column;align-items:flex-end;padding:.55rem .8rem;cursor:pointer;font-size:.78rem;color:var(--text-muted,#888);border-bottom:1px solid var(--border-color,rgba(255,255,255,.08));gap:.05rem;user-select:none;transition:background .15s,color .15s;min-width:84px;">
|
|
117
|
+
<span style="font-size:.6rem;opacity:.55;letter-spacing:.06em;text-transform:uppercase;line-height:1.2;">Top</span>
|
|
118
|
+
<span style="font-weight:600;">Right ↗</span>
|
|
119
|
+
</div>
|
|
120
|
+
|
|
121
|
+
<div class="ss-pos-btn" data-pos="left-center"
|
|
122
|
+
style="display:flex;flex-direction:column;align-items:flex-start;padding:.55rem .8rem;cursor:pointer;font-size:.78rem;color:var(--text-muted,#888);border-right:1px solid var(--border-color,rgba(255,255,255,.08));border-bottom:1px solid var(--border-color,rgba(255,255,255,.08));gap:.05rem;user-select:none;transition:background .15s,color .15s;min-width:84px;">
|
|
123
|
+
<span style="font-size:.6rem;opacity:.55;letter-spacing:.06em;text-transform:uppercase;line-height:1.2;">Side</span>
|
|
124
|
+
<span style="font-weight:600;">← Left</span>
|
|
125
|
+
</div>
|
|
126
|
+
<div class="ss-pos-btn" data-pos="right-center"
|
|
127
|
+
style="display:flex;flex-direction:column;align-items:flex-end;padding:.55rem .8rem;cursor:pointer;font-size:.78rem;color:var(--text-muted,#888);border-bottom:1px solid var(--border-color,rgba(255,255,255,.08));gap:.05rem;user-select:none;transition:background .15s,color .15s;min-width:84px;">
|
|
128
|
+
<span style="font-size:.6rem;opacity:.55;letter-spacing:.06em;text-transform:uppercase;line-height:1.2;">Side</span>
|
|
129
|
+
<span style="font-weight:600;">Right →</span>
|
|
130
|
+
</div>
|
|
131
|
+
|
|
132
|
+
<div class="ss-pos-btn" data-pos="bottom-left"
|
|
133
|
+
style="display:flex;flex-direction:column;align-items:flex-start;padding:.55rem .8rem;cursor:pointer;font-size:.78rem;color:var(--text-muted,#888);border-right:1px solid var(--border-color,rgba(255,255,255,.08));gap:.05rem;user-select:none;transition:background .15s,color .15s;min-width:84px;">
|
|
134
|
+
<span style="font-weight:600;">↙ Left</span>
|
|
135
|
+
<span style="font-size:.6rem;opacity:.55;letter-spacing:.06em;text-transform:uppercase;line-height:1.2;">Bottom</span>
|
|
136
|
+
</div>
|
|
137
|
+
<div class="ss-pos-btn" data-pos="bottom-right"
|
|
138
|
+
style="display:flex;flex-direction:column;align-items:flex-end;padding:.55rem .8rem;cursor:pointer;font-size:.78rem;color:var(--text-muted,#888);gap:.05rem;user-select:none;transition:background .15s,color .15s;min-width:84px;">
|
|
139
|
+
<span style="font-weight:600;">Right ↘</span>
|
|
140
|
+
<span style="font-size:.6rem;opacity:.55;letter-spacing:.06em;text-transform:uppercase;line-height:1.2;">Bottom</span>
|
|
141
|
+
</div>
|
|
142
|
+
|
|
143
|
+
</div>
|
|
144
|
+
<input type="hidden" id="field-position" value="bottom-right">
|
|
145
|
+
</div>
|
|
146
|
+
|
|
147
|
+
<div class="col-sm-3">
|
|
148
|
+
<label class="form-label">Edge offset</label>
|
|
149
|
+
<div style="display:flex;flex-direction:column;gap:.55rem;">
|
|
150
|
+
<div style="display:flex;align-items:center;gap:.4rem;">
|
|
151
|
+
<span style="font-size:.75rem;color:var(--text-muted,#888);width:22px;">H</span>
|
|
152
|
+
<input id="field-offset-x" type="number" class="form-input" min="0" max="500"
|
|
153
|
+
placeholder="32" style="max-width:80px;">
|
|
154
|
+
<span class="text-muted" style="font-size:.8rem;">px</span>
|
|
155
|
+
</div>
|
|
156
|
+
<div style="display:flex;align-items:center;gap:.4rem;">
|
|
157
|
+
<span style="font-size:.75rem;color:var(--text-muted,#888);width:22px;">V</span>
|
|
158
|
+
<input id="field-offset-y" type="number" class="form-input" min="0" max="500"
|
|
159
|
+
placeholder="32" style="max-width:80px;">
|
|
160
|
+
<span class="text-muted" style="font-size:.8rem;">px</span>
|
|
161
|
+
</div>
|
|
162
|
+
</div>
|
|
163
|
+
<p class="form-hint text-muted" style="margin-top:.35rem;font-size:.75rem;">Distance
|
|
164
|
+
from the screen edge.</p>
|
|
165
|
+
</div>
|
|
166
|
+
|
|
167
|
+
</div>
|
|
168
|
+
</div>
|
|
169
|
+
|
|
170
|
+
</div>
|
|
42
171
|
</div>
|
|
43
172
|
</div>
|
|
44
173
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
<
|
|
49
|
-
|
|
174
|
+
<!-- How it works Tab -->
|
|
175
|
+
<div class="tab-panel" id="tab-how-it-works">
|
|
176
|
+
<div class="card mb-4" style="margin-top:1rem;">
|
|
177
|
+
<div class="card-body">
|
|
178
|
+
<p class="text-muted mb-2">Site Search adds a search icon to the public navbar. Visitors can click
|
|
179
|
+
it or use
|
|
180
|
+
the keyboard shortcut to open a full-screen overlay with live results.</p>
|
|
181
|
+
<ul class="text-muted" style="padding-left:1.25rem;line-height:1.8;">
|
|
182
|
+
<li>Results are weighted: title matches score highest, followed by tags, description, and page
|
|
183
|
+
content.
|
|
184
|
+
</li>
|
|
185
|
+
<li>Draft pages and private pages are excluded from results.</li>
|
|
186
|
+
<li>Use <kbd>↑</kbd> <kbd>↓</kbd> to navigate results, <kbd>↵</kbd> to open, <kbd>Esc</kbd> to
|
|
187
|
+
close.
|
|
188
|
+
</li>
|
|
189
|
+
</ul>
|
|
190
|
+
</div>
|
|
50
191
|
</div>
|
|
51
192
|
</div>
|
|
52
193
|
|
|
53
194
|
</div>
|
|
54
195
|
</div>
|
|
55
|
-
|
|
56
|
-
<div class="card mb-4">
|
|
57
|
-
<div class="card-header"><h2>How it works</h2></div>
|
|
58
|
-
<div class="card-body">
|
|
59
|
-
<p class="text-muted mb-2">Site Search adds a search icon to the public navbar. Visitors can click it or use
|
|
60
|
-
the keyboard shortcut to open a full-screen overlay with live results.</p>
|
|
61
|
-
<ul class="text-muted" style="padding-left:1.25rem;line-height:1.8;">
|
|
62
|
-
<li>Results are weighted: title matches score highest, followed by tags, description, and page content.</li>
|
|
63
|
-
<li>Draft pages and private pages are excluded from results.</li>
|
|
64
|
-
<li>Use <kbd>↑</kbd> <kbd>↓</kbd> to navigate results, <kbd>↵</kbd> to open, <kbd>Esc</kbd> to close.</li>
|
|
65
|
-
</ul>
|
|
66
|
-
</div>
|
|
67
|
-
</div>
|
|
@@ -14,19 +14,86 @@ export const siteSearchView = {
|
|
|
14
14
|
E.toast('Could not load settings.', {type: 'error'});
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
+
// ---- Basic settings ----
|
|
17
18
|
$container.find('#field-placeholder').val(settings.placeholder || 'Search pages...');
|
|
18
19
|
$container.find('#field-keyboard-shortcut').prop('checked', settings.keyboardShortcut !== false);
|
|
19
20
|
$container.find('#field-max-results').val(settings.maxResults ?? 10);
|
|
20
21
|
$container.find('#field-min-query-length').val(settings.minQueryLength ?? 2);
|
|
21
22
|
$container.find('#field-debounce-ms').val(settings.debounceMs ?? 300);
|
|
22
23
|
|
|
24
|
+
// ---- Position settings ----
|
|
25
|
+
const displayMode = settings.displayMode || 'navbar';
|
|
26
|
+
const fieldMode = document.getElementById('field-display-mode');
|
|
27
|
+
const fieldPos = document.getElementById('field-position');
|
|
28
|
+
const fieldOffX = document.getElementById('field-offset-x');
|
|
29
|
+
const fieldOffY = document.getElementById('field-offset-y');
|
|
30
|
+
const fieldIconOnly = document.getElementById('field-icon-only');
|
|
31
|
+
const posSection = document.getElementById('ss-pos-section');
|
|
32
|
+
const posGrid = document.getElementById('ss-pos-grid');
|
|
33
|
+
const modeBar = document.getElementById('ss-display-mode');
|
|
34
|
+
|
|
35
|
+
if (fieldMode) fieldMode.value = displayMode;
|
|
36
|
+
if (fieldPos) fieldPos.value = settings.position ?? 'bottom-right';
|
|
37
|
+
if (fieldOffX) fieldOffX.value = settings.offsetX ?? 32;
|
|
38
|
+
if (fieldOffY) fieldOffY.value = settings.offsetY ?? 32;
|
|
39
|
+
if (fieldIconOnly) fieldIconOnly.checked = settings.iconOnly !== false;
|
|
40
|
+
|
|
41
|
+
function applyMode(mode) {
|
|
42
|
+
if (fieldMode) fieldMode.value = mode;
|
|
43
|
+
if (posSection) posSection.style.display = mode === 'floating' ? '' : 'none';
|
|
44
|
+
if (modeBar) {
|
|
45
|
+
modeBar.querySelectorAll('.ss-mode-btn').forEach(function (btn) {
|
|
46
|
+
const active = btn.getAttribute('data-mode') === mode;
|
|
47
|
+
btn.classList.toggle('btn-primary', active);
|
|
48
|
+
btn.classList.toggle('btn-secondary', !active);
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function updatePosBtns(pos) {
|
|
54
|
+
document.querySelectorAll('.ss-pos-btn').forEach(function (btn) {
|
|
55
|
+
const active = btn.getAttribute('data-pos') === pos;
|
|
56
|
+
btn.style.background = active ? 'var(--dm-primary, #5b8cff)' : '';
|
|
57
|
+
btn.style.color = active ? '#fff' : '';
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
applyMode(displayMode);
|
|
62
|
+
updatePosBtns(settings.position || 'bottom-right');
|
|
63
|
+
|
|
64
|
+
// Mode toggle buttons
|
|
65
|
+
if (modeBar) {
|
|
66
|
+
modeBar.addEventListener('click', function (e) {
|
|
67
|
+
const btn = e.target.closest('.ss-mode-btn');
|
|
68
|
+
if (!btn) return;
|
|
69
|
+
applyMode(btn.getAttribute('data-mode'));
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// Position grid
|
|
74
|
+
if (posGrid) {
|
|
75
|
+
posGrid.addEventListener('click', function (e) {
|
|
76
|
+
const btn = e.target.closest('[data-pos]');
|
|
77
|
+
if (!btn) return;
|
|
78
|
+
const pos = btn.getAttribute('data-pos');
|
|
79
|
+
if (fieldPos) fieldPos.value = pos;
|
|
80
|
+
updatePosBtns(pos);
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// ---- Save ----
|
|
23
85
|
$container.find('#save-settings-btn').off('click').on('click', async () => {
|
|
24
86
|
const data = {
|
|
25
87
|
placeholder: $container.find('#field-placeholder').val() || 'Search pages...',
|
|
26
88
|
keyboardShortcut: $container.find('#field-keyboard-shortcut').prop('checked'),
|
|
27
89
|
maxResults: parseInt($container.find('#field-max-results').val(), 10) || 10,
|
|
28
90
|
minQueryLength: parseInt($container.find('#field-min-query-length').val(), 10) || 2,
|
|
29
|
-
debounceMs: parseInt($container.find('#field-debounce-ms').val(), 10) || 300
|
|
91
|
+
debounceMs: parseInt($container.find('#field-debounce-ms').val(), 10) || 300,
|
|
92
|
+
displayMode: fieldMode ? fieldMode.value : 'navbar',
|
|
93
|
+
position: fieldPos ? fieldPos.value : 'bottom-right',
|
|
94
|
+
offsetX: fieldOffX ? (parseInt(fieldOffX.value, 10) || 32) : 32,
|
|
95
|
+
offsetY: fieldOffY ? (parseInt(fieldOffY.value, 10) || 32) : 32,
|
|
96
|
+
iconOnly: fieldIconOnly ? fieldIconOnly.checked : true
|
|
30
97
|
};
|
|
31
98
|
|
|
32
99
|
try {
|
|
@@ -40,6 +107,10 @@ export const siteSearchView = {
|
|
|
40
107
|
}
|
|
41
108
|
});
|
|
42
109
|
|
|
110
|
+
// Initialise tabs
|
|
111
|
+
const tabsEl = $container.find('#ss-settings-tabs').get(0);
|
|
112
|
+
if (tabsEl) E.tabs(tabsEl);
|
|
113
|
+
|
|
43
114
|
Domma.icons.scan();
|
|
44
115
|
}
|
|
45
116
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
<link rel="stylesheet" href="/plugins/site-search/public/search.css">
|
|
1
|
+
<link rel="stylesheet" href="/plugins/site-search/public/search.css?v=2">
|
|
@@ -1 +1 @@
|
|
|
1
|
-
.site-search-trigger{display:inline-flex;align-items:center;justify-content:center;background:none;border:none;cursor:pointer;padding:6px 8px;border-radius:var(--dm-radius, 6px);color:inherit;opacity:.75;transition:opacity .15s,background .15s;font-size:var(--dm-font-size-sm, 14px)}.site-search-trigger:hover{opacity:1;background:var(--dm-surface-hover, rgba(0, 0, 0, .06))}.site-search-trigger svg,.site-search-trigger span[data-icon]{width:18px;height:18px}.site-search-shortcut-hint{display:inline-block;font-size:11px;line-height:1;padding:2px 5px;border-radius:4px;border:1px solid var(--dm-border, rgba(0, 0, 0, .15));color:var(--dm-text-muted, #888);margin-left:4px;vertical-align:middle;font-family:var(--dm-font-mono, monospace)}.site-search-overlay{position:fixed;inset:0;z-index:10000;background:#00000073;backdrop-filter:blur(3px);-webkit-backdrop-filter:blur(3px);display:flex;align-items:flex-start;justify-content:center;padding-top:10vh;animation:ss-overlay-in .15s ease}@keyframes ss-overlay-in{0%{opacity:0}to{opacity:1}}.site-search-panel{width:100%;max-width:600px;margin:0 16px;border-radius:var(--dm-radius-lg, 10px);box-shadow:0
|
|
1
|
+
.site-search-trigger{display:inline-flex;align-items:center;justify-content:center;background:none;border:none;cursor:pointer;padding:6px 8px;border-radius:var(--dm-radius, 6px);color:inherit;opacity:.75;transition:opacity .15s,background .15s;font-size:var(--dm-font-size-sm, 14px)}.site-search-trigger:hover{opacity:1;background:var(--dm-surface-hover, rgba(0, 0, 0, .06))}.site-search-trigger svg,.site-search-trigger span[data-icon]{width:18px;height:18px}.site-search-shortcut-hint{display:inline-block;font-size:11px;line-height:1;padding:2px 5px;border-radius:4px;border:1px solid var(--dm-border, rgba(0, 0, 0, .15));color:var(--dm-text-muted, #888);margin-left:4px;vertical-align:middle;font-family:var(--dm-font-mono, monospace)}.site-search-overlay{position:fixed;inset:0;z-index:10000;background:#00000073;backdrop-filter:blur(3px);-webkit-backdrop-filter:blur(3px);display:flex;align-items:flex-start;justify-content:center;padding-top:10vh;animation:ss-overlay-in .15s ease}@keyframes ss-overlay-in{0%{opacity:0}to{opacity:1}}.site-search-panel{width:100%;max-width:600px;margin:0 16px;border-radius:var(--dm-radius-lg, 10px);background:#1e2030;color:#e8eaf0;border:1px solid rgba(255,255,255,.1);box-shadow:0 24px 64px #0009;overflow:hidden;animation:ss-panel-in .15s ease}@keyframes ss-panel-in{0%{transform:translateY(-12px);opacity:0}to{transform:translateY(0);opacity:1}}.site-search-header{display:flex;align-items:center;padding:12px 16px;border-bottom:1px solid rgba(255,255,255,.08);gap:8px}.site-search-header span[data-icon],.site-search-header svg{width:18px;height:18px;flex-shrink:0;opacity:.45;color:#e8eaf0}.site-search-input{flex:1;border:none;outline:none;background:transparent;font-size:var(--dm-font-size-lg, 16px);color:#e8eaf0;font-family:var(--dm-font-sans, sans-serif);padding:0}.site-search-input::placeholder{color:#e8eaf066;opacity:1}.site-search-close-btn{display:inline-flex;align-items:center;justify-content:center;background:none;border:1px solid rgba(255,255,255,.15);cursor:pointer;color:#e8eaf080;border-radius:var(--dm-radius, 6px);padding:4px 8px;font-size:12px;font-family:var(--dm-font-mono, monospace);transition:color .15s,border-color .15s;flex-shrink:0}.site-search-close-btn:hover{color:#e8eaf0;border-color:#ffffff4d}.site-search-results{max-height:60vh;overflow-y:auto;padding:8px 0}.site-search-result{display:block;padding:10px 16px;text-decoration:none;color:inherit;border-left:3px solid transparent;transition:background .1s,border-color .1s;cursor:pointer}.site-search-result:hover,.site-search-result.active{background:#ffffff0f;border-left-color:var(--dm-primary, #5b8cff)}.site-search-result-title{font-weight:600;font-size:var(--dm-font-size-sm, 14px);margin-bottom:2px;color:#e8eaf0}.site-search-result-snippet{font-size:12px;color:#e8eaf08c;line-height:1.4;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.site-search-result-snippet mark{background:#5b8cff40;color:#e8eaf0;border-radius:2px;padding:0 1px}.site-search-loading,.site-search-empty{padding:24px 16px;text-align:center;color:#e8eaf073;font-size:var(--dm-font-size-sm, 14px)}.site-search-loading-dots{display:inline-flex;gap:4px}.site-search-loading-dots span{width:6px;height:6px;border-radius:50%;background:#e8eaf066;animation:ss-dot-pulse 1.2s ease-in-out infinite}.site-search-loading-dots span:nth-child(2){animation-delay:.2s}.site-search-loading-dots span:nth-child(3){animation-delay:.4s}@keyframes ss-dot-pulse{0%,80%,to{transform:scale(.6);opacity:.4}40%{transform:scale(1);opacity:1}}.site-search-results:not(:empty){border-top:1px solid rgba(255,255,255,.06)}.site-search-footer{padding:6px 16px;border-top:1px solid rgba(255,255,255,.06);display:flex;gap:12px;font-size:11px;color:#e8eaf059}.site-search-footer kbd{display:inline-block;padding:1px 4px;border-radius:3px;border:1px solid rgba(255,255,255,.15);font-family:var(--dm-font-mono, monospace);font-size:10px}@media(max-width:640px){.site-search-overlay{padding-top:5vh;align-items:flex-start}.site-search-panel{margin:0 8px;border-radius:var(--dm-radius, 6px)}.site-search-results{max-height:70vh}.site-search-shortcut-hint{display:none}}.site-search-floating-trigger{position:fixed;z-index:9999;width:52px;height:52px;border-radius:50%;border:1px solid var(--dm-border, rgba(0, 0, 0, .12));cursor:pointer;display:flex;align-items:center;justify-content:center;gap:8px;background:var(--dm-surface, #fff);color:var(--dm-text, #111);box-shadow:0 4px 16px #00000024;transition:background .15s,color .15s,border-color .15s,transform .15s,box-shadow .15s;outline:none;white-space:nowrap}.site-search-floating-trigger:hover{background:var(--dm-primary, #5b8cff);color:#fff;border-color:var(--dm-primary, #5b8cff);box-shadow:0 6px 20px #00000038;transform:scale(1.05)}.site-search-floating-trigger:active{transform:scale(.97)}.site-search-floating-trigger svg,.site-search-floating-trigger [data-icon]{width:20px;height:20px;flex-shrink:0;pointer-events:none}.site-search-floating-trigger--pill{width:auto;height:44px;border-radius:999px;padding:0 18px 0 14px}.site-search-floating-label{font-size:.875rem;font-weight:500;letter-spacing:.01em;pointer-events:none}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
(function(){"use strict";var
|
|
1
|
+
(function(){"use strict";var l=window.__SITE_SEARCH__||{},N=l.placeholder||"Search pages...",g=l.keyboardShortcut!==!1,w=l.debounceMs||300,D=l.displayMode||"navbar",y=l.iconOnly!==!1,u=null,s=null,c=null,p=null,f=!1;function h(){var t=document.querySelector("#site-navbar, .navbar");if(t){var e=t.querySelector(".navbar-actions");if(!e){var n=t.querySelector(".navbar-container")||t;e=document.createElement("div"),e.className="navbar-actions",n.appendChild(e)}if(!e.querySelector(".site-search-trigger")){var r=/Mac|iPhone|iPad|iPod/.test(navigator.platform||navigator.userAgent),o=r?"\u2318K":"Ctrl+K",a=document.createElement("button");a.className="navbar-action-link site-search-trigger",a.setAttribute("aria-label","Search"),a.setAttribute("type","button");var i=document.createElement("span");if(i.setAttribute("data-icon","search"),a.appendChild(i),g){var d=document.createElement("span");d.className="site-search-shortcut-hint",d.textContent=o,a.appendChild(d)}e.insertBefore(a,e.firstChild),a.addEventListener("click",b),window.Domma&&Domma.icons&&Domma.icons.scan&&Domma.icons.scan(a)}}}function L(){if(document.querySelector("#site-navbar .navbar-actions, .navbar .navbar-actions")){h();return}var t=new MutationObserver(function(){var e=document.querySelector("#site-navbar, .navbar");e&&(t.disconnect(),h())});t.observe(document.body,{childList:!0,subtree:!0}),setTimeout(function(){t.disconnect(),h()},5e3)}function k(){var t=document.createElement("div");t.className="site-search-overlay",t.setAttribute("role","dialog"),t.setAttribute("aria-modal","true"),t.setAttribute("aria-label","Site search");var e=document.createElement("div");e.className="site-search-panel",e.setAttribute("role","search");var n=document.createElement("div");n.className="site-search-header";var r=document.createElement("span");r.setAttribute("data-icon","search"),n.appendChild(r),s=document.createElement("input"),s.className="site-search-input",s.type="search",s.setAttribute("autocomplete","off"),s.setAttribute("autocorrect","off"),s.setAttribute("spellcheck","false"),s.setAttribute("aria-label","Search"),s.placeholder=N,n.appendChild(s);var o=document.createElement("button");o.className="site-search-close-btn",o.setAttribute("type","button"),o.setAttribute("aria-label","Close search"),o.textContent="Esc",n.appendChild(o),e.appendChild(n),c=document.createElement("div"),c.className="site-search-results",c.setAttribute("role","listbox"),c.setAttribute("aria-live","polite"),e.appendChild(c);var a=document.createElement("div");return a.className="site-search-footer",a.innerHTML="<span><kbd>\u2191</kbd><kbd>\u2193</kbd> navigate</span><span><kbd>\u21B5</kbd> open</span><span><kbd>Esc</kbd> close</span>",e.appendChild(a),t.appendChild(e),t.addEventListener("click",function(i){i.target===t&&v()}),o.addEventListener("click",v),s.addEventListener("input",function(){clearTimeout(p);var i=s.value.trim();if(!i){E();return}p=setTimeout(function(){T(i)},w)}),s.addEventListener("keydown",q),window.Domma&&Domma.icons&&Domma.icons.scan&&Domma.icons.scan(n),t}function b(){f||(f=!0,u=k(),document.body.appendChild(u),document.body.style.overflow="hidden",setTimeout(function(){s&&s.focus()},30))}function v(){f&&(f=!1,clearTimeout(p),u&&u.parentNode&&u.parentNode.removeChild(u),u=null,s=null,c=null,document.body.style.overflow="")}function T(t){c&&(x(),fetch("/api/plugins/site-search/search?q="+encodeURIComponent(t)).then(function(e){return e.json()}).then(function(e){M(e.results||[],t)}).catch(function(){E();var e=document.createElement("div");e.className="site-search-empty",e.textContent="Search unavailable. Please try again.",c.appendChild(e)}))}function x(){c&&(c.innerHTML='<div class="site-search-loading"><div class="site-search-loading-dots"><span></span><span></span><span></span></div></div>')}function E(){c&&(c.innerHTML="")}function M(t,e){if(c){if(c.innerHTML="",!t.length){var n=document.createElement("div");n.className="site-search-empty",n.textContent='No results found for "'+e+'"',c.appendChild(n);return}for(var r=document.createDocumentFragment(),o=0;o<t.length;o++){var a=t[o],i=document.createElement("a");i.className="site-search-result",i.href=a.url||"/",i.setAttribute("role","option"),i.setAttribute("tabindex","-1"),i.setAttribute("data-index",String(o));var d=document.createElement("div");if(d.className="site-search-result-title",C(d,a.title||"Untitled",e),i.appendChild(d),a.snippet){var m=document.createElement("div");m.className="site-search-result-snippet",C(m,a.snippet,e),i.appendChild(m)}i.addEventListener("click",v),r.appendChild(i)}c.appendChild(r)}}function C(t,e,n){if(!n){t.textContent=e;return}var r=n.trim().split(/\s+/).filter(Boolean);if(!r.length){t.textContent=e;return}var o;try{o=new RegExp("("+r.map(function(m){return m.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}).join("|")+")","gi")}catch{t.textContent=e;return}for(var a=e.split(o),i=0;i<a.length;i++){if(o.test(a[i])){var d=document.createElement("mark");d.textContent=a[i],t.appendChild(d)}else t.appendChild(document.createTextNode(a[i]));o.lastIndex=0}}function q(t){if(t.key==="Escape"){t.preventDefault(),v();return}if(c){var e=c.querySelectorAll(".site-search-result");if(e.length){for(var n=c.querySelector(".site-search-result.active"),r=-1,o=0;o<e.length;o++)if(e[o]===n){r=o;break}if(t.key==="ArrowDown")t.preventDefault(),A(e,r<e.length-1?r+1:0);else if(t.key==="ArrowUp")t.preventDefault(),A(e,r>0?r-1:e.length-1);else if(t.key==="Enter"&&n){t.preventDefault();var a=n.getAttribute("href");v(),window.location.href=a}}}}function A(t,e){for(var n=0;n<t.length;n++)t[n].classList.toggle("active",n===e);t[e]&&t[e].scrollIntoView({block:"nearest"})}g&&document.addEventListener("keydown",function(t){if((t.metaKey||t.ctrlKey)&&t.key==="k"){var e=document.activeElement&&document.activeElement.tagName;if((e==="INPUT"||e==="TEXTAREA"||e==="SELECT")&&!f)return;t.preventDefault(),f?v():b()}});function O(t,e,n,r){var o=e==="left-center"||e==="bottom-left"||e==="top-left",a=e==="bottom-left"||e==="bottom-right",i=e==="top-left"||e==="top-right";Object.assign(t.style,{right:o?"auto":n+"px",left:o?n+"px":"auto",top:i?r+"px":a?"auto":"50vh",bottom:a?r+"px":"auto",transform:i||a?"none":"translateY(-50%)"})}function H(){if(!document.querySelector(".site-search-floating-trigger")){var t=l.position||"bottom-right",e=l.offsetX!=null?l.offsetX:32,n=l.offsetY!=null?l.offsetY:32,r=document.createElement("button");r.className="site-search-floating-trigger"+(y?"":" site-search-floating-trigger--pill"),r.setAttribute("type","button"),r.setAttribute("aria-label","Search");var o=document.createElement("span");if(o.setAttribute("data-icon","search"),r.appendChild(o),!y){var a=document.createElement("span");a.className="site-search-floating-label",a.textContent="Search",r.appendChild(a)}O(r,t,e,n),document.body.appendChild(r),r.addEventListener("click",b),window.Domma&&Domma.icons&&Domma.icons.scan&&Domma.icons.scan(r)}}function S(){D==="floating"?H():L()}document.readyState==="loading"?document.addEventListener("DOMContentLoaded",S):S()})();
|
|
@@ -47,14 +47,8 @@
|
|
|
47
47
|
<button class="btn btn-sm filter-btn" data-filter="completed">Completed</button>
|
|
48
48
|
</div>
|
|
49
49
|
|
|
50
|
-
<!-- Todo
|
|
51
|
-
<
|
|
52
|
-
|
|
53
|
-
<!-- Empty state -->
|
|
54
|
-
<div id="empty-state" style="display:none;text-align:center;padding:40px 0;color:var(--dm-text-muted);">
|
|
55
|
-
<span data-icon="check-circle" data-icon-size="48" style="display:block;margin-bottom:12px;opacity:0.4;"></span>
|
|
56
|
-
<p style="margin:0;font-size:0.95rem;">No tasks yet. Add one above to get started.</p>
|
|
57
|
-
</div>
|
|
50
|
+
<!-- Todo table -->
|
|
51
|
+
<div id="todo-table"></div>
|
|
58
52
|
|
|
59
53
|
</div>
|
|
60
54
|
</div>
|