@dinoreic/fez 0.4.0 → 0.5.2

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.
@@ -2,98 +2,289 @@
2
2
  const loadDefaults = () => {
3
3
  // include fez component by name
4
4
  //<fez-component name="some-node" :props="fez.props"></fez-component>
5
- Fez('fez-component', class {
6
- init(props) {
7
- const tag = document.createElement(props.name)
8
- tag.props = props.props || props['data-props'] || props
5
+ Fez(
6
+ "fez-component",
7
+ class {
8
+ init(props) {
9
+ const tag = document.createElement(props.name);
10
+ tag.props = props.props || props["data-props"] || props;
9
11
 
10
- while (this.root.firstChild) {
11
- this.root.parentNode.insertBefore(this.root.lastChild, tag.nextSibling);
12
- }
12
+ while (this.root.firstChild) {
13
+ this.root.parentNode.insertBefore(
14
+ this.root.lastChild,
15
+ tag.nextSibling,
16
+ );
17
+ }
13
18
 
14
- this.root.innerHTML = ''
15
- this.root.appendChild(tag)
16
- }
17
- })
19
+ this.root.innerHTML = "";
20
+ this.root.appendChild(tag);
21
+ }
22
+ },
23
+ );
18
24
 
19
25
  // include remote data from url
20
26
  // <fez-include src="./demo/fez/ui-slider.html"></fez-include>
21
- Fez('fez-include', class {
22
- init(props) {
23
- Fez.fetch(props.src, (data)=>{
24
- const dom = Fez.domRoot(data)
25
- Fez.head(dom) // include scripts and load fez components
26
- this.root.innerHTML = dom.innerHTML
27
- })
28
- }
29
- })
27
+ Fez(
28
+ "fez-include",
29
+ class {
30
+ init(props) {
31
+ Fez.fetch(props.src, (data) => {
32
+ const dom = Fez.domRoot(data);
33
+ Fez.head(dom); // include scripts and load fez components
34
+ this.root.innerHTML = dom.innerHTML;
35
+ });
36
+ }
37
+ },
38
+ );
30
39
 
31
- // include remote data from url
32
- // <fez-inline :state="{count: 0}">
33
- // <button onclick="fez.state.count += 1">&plus;</button>
34
- // {{ state.count }} * {{ state.count }} = {{ state.count * state.count }}
35
- // </fez-inline>
36
- Fez('fez-inline', class {
37
- init(props) {
38
- const html = this.root.innerHTML
39
-
40
- if (this.root.innerHTML.includes('<')) {
41
- const hash = Fez.fnv1(this.root.outerHTML)
42
- const nodeName = `inline-${hash}`
43
- Fez(nodeName, class {
44
- HTML = html
45
- init() {
46
- Object.assign(this.state, props.state || {})
40
+ // Show node only if test validates
41
+ // <fez-if if="window.foo">...
42
+ Fez(
43
+ "fez-if",
44
+ class {
45
+ init(props) {
46
+ const test = new Function(`return (${props.if || props.test})`);
47
+ if (!test()) {
48
+ this.root.remove();
49
+ }
50
+ }
51
+ },
52
+ );
53
+
54
+ // Render all components with their demos
55
+ // <fez-demo></fez-demo>
56
+ // <fez-demo name="ui-clock"></fez-demo>
57
+ // Also supports ?fez=NAME query string
58
+ Fez(
59
+ "fez-demo",
60
+ class {
61
+ init(props) {
62
+ this.state.ready = false;
63
+ this.state.components = [];
64
+ this.state.filtered = false;
65
+ this.state.showAllUrl = "";
66
+
67
+ // Check for name from props or query string
68
+ const urlParams = new URLSearchParams(window.location.search);
69
+ const name = props.name || urlParams.get("fez");
70
+
71
+ // If filtering, store URL without ?fez param
72
+ if (urlParams.get("fez")) {
73
+ const url = new URL(window.location.href);
74
+ url.searchParams.delete("fez");
75
+ this.state.showAllUrl = url.pathname + url.search;
76
+ this.state.filtered = true;
77
+ }
78
+
79
+ // Wait for components to be loaded, then render
80
+ const checkReady = () => {
81
+ // If name provided, render only that component
82
+ if (name) {
83
+ if (Fez.index[name]?.demo) {
84
+ this.state.components = [name];
85
+ this.state.ready = true;
86
+ } else {
87
+ setTimeout(checkReady, 100);
88
+ }
89
+ } else {
90
+ // Render all components that have demos
91
+ const names = Fez.index.withDemo().sort();
92
+ if (names.length > 0) {
93
+ this.state.components = names;
94
+ this.state.ready = true;
95
+ } else {
96
+ setTimeout(checkReady, 100);
97
+ }
47
98
  }
48
- })
49
-
50
- const el = document.createElement(nodeName)
51
- this.root.after(this.root.lastChild, el);
52
- this.root.remove()
53
- }
54
- }
55
- })
56
-
57
- // Memory store for memoization
58
- const memoStore = new Map()
59
-
60
- // memoize component content by key
61
- // <fez-memoize key="unique-key">content to memoize</fez-memoize>
62
- Fez('fez-memoize', class {
63
- init(props) {
64
- if (!props.key) {
65
- Fez.error('fez-memoize: key prop is required')
66
- return
67
- }
68
-
69
- if (memoStore.has(props.key)) {
70
- // Restore from memory in init
71
- const storedNode = memoStore.get(props.key)
72
- Fez.log(`Memoize - key: "${props.key}" - restore`)
73
- this.root.innerHTML = ''
74
- this.root.appendChild(storedNode.cloneNode(true))
75
- }
76
- }
77
-
78
- onMount(props) {
79
- // Only store if not already in memory
80
- if (!memoStore.has(props.key)) {
81
- requestAnimationFrame(() => {
82
- // Store current DOM content
83
- const contentNode = document.createElement('div')
84
- contentNode.innerHTML = this.root.innerHTML
85
- Fez.log(`Memoize - key: "${props.key}" - set`)
86
- memoStore.set(props.key, contentNode)
87
- })
88
- }
89
- }
90
- })
91
- }
99
+ };
100
+ checkReady();
101
+ }
102
+
103
+ showHtml(name) {
104
+ const html = Fez.index[name]?.demo || "No demo HTML";
105
+ Fez.log("Demo HTML: " + name + "\n\n" + html);
106
+ }
107
+
108
+ showFez(name) {
109
+ Fez.log(
110
+ "Fez source: " +
111
+ name +
112
+ "\n\n" +
113
+ (Fez.index[name]?.source || "Source not available"),
114
+ );
115
+ }
116
+
117
+ openSingle(name) {
118
+ const url = new URL(window.location.href);
119
+ url.searchParams.set("fez", name);
120
+ window.location.href = url.toString();
121
+ }
122
+
123
+ openCodePen(name) {
124
+ const demo = Fez.index[name]?.demo || "";
125
+ const code = Fez.index[name]?.source || "";
126
+ const body = [
127
+ '<link rel="stylesheet" href="//cdn.simplecss.org/simple.css" />\n<scr' +
128
+ 'ipt src="//dux.github.io/fez/dist/fez.js"></scr' +
129
+ "ipt>",
130
+ "<!-- FEZ code start -->\n<x" +
131
+ `mp fez="${name}">\n${code}\n</xm` +
132
+ "p>\n<!-- FEZ code end -->",
133
+ `<!-- HTML code start -->\n${demo}\n<!-- HTML code end -->`,
134
+ ];
135
+
136
+ const data = {
137
+ title: "Fez component - " + name,
138
+ html: body.join("\n\n"),
139
+ css: "body { padding-top: 50px; }",
140
+ js: "",
141
+ editors: "100",
142
+ };
143
+
144
+ const form = document.createElement("form");
145
+ form.method = "POST";
146
+ form.action = "https://codepen.io/pen/define";
147
+ form.target = "_blank";
148
+
149
+ const input = document.createElement("input");
150
+ input.type = "hidden";
151
+ input.name = "data";
152
+ input.value = JSON.stringify(data);
153
+
154
+ form.appendChild(input);
155
+ document.body.appendChild(form);
156
+ form.submit();
157
+ document.body.removeChild(form);
158
+ }
159
+
160
+ renderDemo(el) {
161
+ const name = el.dataset.name;
162
+ Fez.index.apply(name, el);
163
+ }
164
+
165
+ renderInfo(el) {
166
+ const name = el.dataset.name;
167
+ const data = Fez.index.get(name);
168
+ if (data.info) {
169
+ el.innerHTML = data.info.innerHTML;
170
+ } else {
171
+ el.innerHTML = "<em>No info available</em>";
172
+ }
173
+ }
174
+
175
+ CSS() {
176
+ return `:fez {
177
+ display: block;
178
+ font-family: system-ui, -apple-system, sans-serif;
179
+ }
180
+ .fez-demo-item {
181
+ margin-bottom: 40px;
182
+ }
183
+ .fez-demo-title {
184
+ display: flex;
185
+ align-items: center;
186
+ gap: 15px;
187
+ font-size: 18px;
188
+ font-weight: 600;
189
+ margin: 0 0 25px 0;
190
+ &::before {
191
+ content: '';
192
+ flex: 1;
193
+ height: 1px;
194
+ background: #ddd;
195
+ }
196
+ &::after {
197
+ content: '';
198
+ flex: 1;
199
+ height: 1px;
200
+ background: #ddd;
201
+ }
202
+ .fez-demo-show-all, .fez-demo-open-single {
203
+ font-size: 14px;
204
+ font-weight: normal;
205
+ color: #666;
206
+ text-decoration: none;
207
+ cursor: pointer;
208
+ &:hover { text-decoration: underline; }
209
+ }
210
+ }
211
+ .fez-demo-cols {
212
+ display: flex;
213
+ gap: 40px;
214
+ @media (max-width: 768px) {
215
+ flex-direction: column;
216
+ gap: 20px;
217
+ }
218
+ }
219
+ .fez-demo-left, .fez-demo-right {
220
+ flex: 1;
221
+ min-width: 0;
222
+ overflow: visible;
223
+ }
224
+ .fez-demo-content {
225
+ min-height: 50px;
226
+ }
227
+ .fez-demo-info {
228
+ background: #fff;
229
+ border: 1px solid #ddd;
230
+ border-radius: 6px;
231
+ padding: 20px;
232
+ line-height: 1.6;
233
+ ul { margin: 0; padding-left: 20px; }
234
+ code { background: #e8e8e8; padding: 2px 5px; border-radius: 3px; font-size: 13px; }
235
+ }
236
+ .fez-demo-buttons {
237
+ margin-top: 30px;
238
+ display: flex;
239
+ gap: 10px;
240
+ }
241
+ .fez-demo-btn {
242
+ padding: 8px 16px;
243
+ border: 1px solid #ccc;
244
+ background: #fff;
245
+ border-radius: 4px;
246
+ cursor: pointer;
247
+ &:hover { background: #f0f0f0; }
248
+ }`;
249
+ }
250
+
251
+ HTML() {
252
+ return `{#if state.ready}
253
+ {#each state.components as name}
254
+ <div class="fez-demo-item">
255
+ <h2 class="fez-demo-title">{name}{#if state.filtered} <a href="{state.showAllUrl}" class="fez-demo-show-all">show all</a>{:else} <a onclick="fez.openSingle('{name}')" class="fez-demo-open-single">open</a>{/if}</h2>
256
+ <div class="fez-demo-cols">
257
+ <div class="fez-demo-left">
258
+ <div class="fez-demo-content" data-name={name} fez-use="renderDemo"></div>
259
+ </div>
260
+ <div class="fez-demo-right">
261
+ <div class="fez-demo-info" data-name={name} fez-use="renderInfo"></div>
262
+ <div class="fez-demo-buttons">
263
+ <button class="fez-demo-btn" onclick="fez.showHtml('{name}')">Demo HTML</button>
264
+ <button class="fez-demo-btn" onclick="fez.showFez('{name}')">Fez Component</button>
265
+ <button class="fez-demo-btn" onclick="fez.openCodePen('{name}')">CodePen</button>
266
+ </div>
267
+ </div>
268
+ </div>
269
+ </div>
270
+ {/each}
271
+ {:else}
272
+ <div style="padding: 40px; text-align: center; color: #888;">Loading components...</div>
273
+ {/if}`;
274
+ }
275
+ },
276
+ );
277
+ };
92
278
 
93
- // Only load defaults if Fez is available
94
- if (typeof Fez !== 'undefined' && Fez) {
95
- loadDefaults()
279
+ // Only load defaults if Fez is available and DOM exists
280
+ if (
281
+ typeof Fez !== "undefined" &&
282
+ Fez &&
283
+ typeof document !== "undefined" &&
284
+ document.head
285
+ ) {
286
+ loadDefaults();
96
287
  }
97
288
 
98
289
  // Export for use in tests
99
- export { loadDefaults }
290
+ export { loadDefaults };