native-document 1.0.9 → 1.0.11

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.
@@ -0,0 +1,383 @@
1
+ # Elements
2
+
3
+ NativeDocument provides a simple and intuitive way to create HTML elements with a declarative syntax. Every HTML element has a corresponding function that creates reactive DOM elements.
4
+
5
+ ## Basic Element Creation
6
+
7
+ ```javascript
8
+ // Simple elements with attributes
9
+ const title = H1({ class: "main-title" }, "Welcome to my app");
10
+ const description = P({ class: "description" }, "This is a paragraph");
11
+
12
+ // Elements without attributes (attributes omitted)
13
+ const simpleTitle = H1("Welcome to my app");
14
+ const simplePara = P("This is a paragraph");
15
+ const container = Div("Content here");
16
+
17
+ // Elements without content
18
+ const separator = Hr();
19
+ const lineBreak = Br();
20
+ ```
21
+
22
+ ## Element Structure
23
+
24
+ All element functions follow the same pattern:
25
+ ```javascript
26
+ ElementName(attributes, children)
27
+ // or
28
+ ElementName(children) // attributes are optional
29
+ ```
30
+
31
+ - **attributes**: Object with HTML attributes (optional, can be `null` or omitted)
32
+ - **children**: Content inside the element (text, number, observable, other elements, or arrays)
33
+
34
+ ## Working with Attributes
35
+
36
+ ```javascript
37
+ // Static attributes
38
+ const link = Link({
39
+ href: "/about",
40
+ class: "nav-link",
41
+ id: "about-link"
42
+ }, "About Us");
43
+
44
+ // Boolean attributes
45
+ const input = Input({
46
+ type: "checkbox",
47
+ checked: true,
48
+ disabled: false
49
+ });
50
+
51
+ // Data attributes
52
+ const element = Div({
53
+ "data-id": "123",
54
+ "data-category": "important"
55
+ }, "Content");
56
+ ```
57
+
58
+ ## Reactive Attributes with Observables
59
+
60
+ ```javascript
61
+ const isVisible = Observable(true);
62
+ const userName = Observable("Guest");
63
+ const theme = Observable("dark");
64
+
65
+ // Reactive attributes
66
+ const greeting = Div({
67
+ class: theme, // Updates when theme changes
68
+ hidden: isVisible.check(val => !val) // Hide when isVisible is false
69
+ }, `Hello ${userName}!`); // Reactive text content
70
+
71
+ // Reactive styles
72
+ const box = Div({
73
+ style: {
74
+ backgroundColor: theme.check(t => t === "dark" ? "#333" : "#fff"),
75
+ color: theme.check(t => t === "dark" ? "#fff" : "#333")
76
+ }
77
+ }, "Themed content");
78
+ ```
79
+
80
+ ## Children and Content
81
+
82
+ ```javascript
83
+ // Text content (no attributes needed)
84
+ const simple = P("Simple text");
85
+
86
+ // Single child element
87
+ const wrapper = Div({ class: "wrapper" },
88
+ P("Wrapped paragraph")
89
+ );
90
+
91
+ // Multiple children as array
92
+ const list = Div({ class: "item-list" }, [
93
+ P("First item"),
94
+ P("Second item"),
95
+ P("Third item")
96
+ ]);
97
+
98
+ // Mixed content
99
+ const mixed = Div([
100
+ H2("Title"),
101
+ "Some text between elements",
102
+ P("A paragraph"),
103
+ Button("Click me")
104
+ ]);
105
+ ```
106
+
107
+ ## Event Handling with .nd API
108
+
109
+ The `.nd` (NativeDocument) API provides a fluent interface for adding functionality to elements.
110
+
111
+ ```javascript
112
+ const button = Button("Click me")
113
+ .nd.on.click(() => {
114
+ console.log("Button clicked!");
115
+ });
116
+
117
+ // With attributes and events
118
+ const styledButton = Button({ class: "btn" }, "Click me")
119
+ .nd.on.click(() => {
120
+ console.log("Button clicked!");
121
+ });
122
+
123
+ // Multiple events
124
+ const input = Input({ type: "text", placeholder: "Type here..." })
125
+ .nd.on.focus(() => console.log("Input focused"))
126
+ .nd.on.blur(() => console.log("Input blurred"))
127
+ .nd.on.input(event => console.log("Input value:", event.target.value));
128
+
129
+ // Or
130
+ const input = Input({ type: "text", placeholder: "Type here..." })
131
+ .nd.on({
132
+ focus: () => console.log("Input focused"),
133
+ blur: () => console.log("Input blurred"),
134
+ input: event => console.log("Input value:", event.target.value)
135
+ });
136
+
137
+ // Prevent default behavior
138
+ const form = Form()
139
+ .nd.on.prevent.submit(event => {
140
+ console.log("Form submitted without page reload");
141
+ // Handle form submission
142
+ });
143
+ ```
144
+
145
+ ## Form Elements and Two-Way Binding
146
+
147
+ ```javascript
148
+ const name = Observable("");
149
+ const email = Observable("");
150
+ const isChecked = Observable(false);
151
+
152
+ // Text input with two-way binding
153
+ const nameInput = Input({
154
+ type: "text",
155
+ value: name, // Automatic two-way binding
156
+ placeholder: "Enter your name"
157
+ });
158
+
159
+ // Email input
160
+ const emailInput = Input({
161
+ type: "email",
162
+ value: email,
163
+ placeholder: "Enter your email"
164
+ });
165
+
166
+ // Checkbox with binding
167
+ const checkbox = Input({
168
+ type: "checkbox",
169
+ checked: isChecked // Automatic two-way binding
170
+ });
171
+ ```
172
+
173
+ ## Conditional Classes and Styles
174
+
175
+ ```javascript
176
+ const isActive = Observable(false);
177
+ const count = Observable(0);
178
+
179
+ // Conditional classes
180
+ const item = Div({
181
+ class: {
182
+ "item": true, // Always present
183
+ "active": isActive, // Present when isActive is true
184
+ "highlighted": count.check(c => c > 5) // Present when count > 5
185
+ }
186
+ }, "List item");
187
+
188
+ // Dynamic styles
189
+ const progress = Div({
190
+ style: {
191
+ width: count.check(c => `${c}%`),
192
+ backgroundColor: count.check(c => c > 50 ? "green" : "red")
193
+ }
194
+ }, "Progress bar");
195
+ ```
196
+
197
+ ## Lifecycle Management
198
+
199
+ ```javascript
200
+ const component = Div("Component content")
201
+ .nd.mounted(element => {
202
+ console.log("Component mounted to DOM");
203
+ // Initialize component
204
+ })
205
+ .nd.unmounted(element => {
206
+ console.log("Component removed from DOM");
207
+ // Cleanup resources
208
+ });
209
+
210
+ // Combined lifecycle
211
+ const widget = Div("Widget")
212
+ .nd.lifecycle({
213
+ mounted: element => console.log("Widget mounted"),
214
+ unmounted: element => console.log("Widget unmounted")
215
+ });
216
+ ```
217
+
218
+ ## Element References
219
+
220
+ ```javascript
221
+ const refs = {};
222
+
223
+ const app = Div([
224
+ Input({ type: "text" })
225
+ .nd.ref(refs, "nameInput"), // Store reference as refs.nameInput
226
+
227
+ Button("Focus Input")
228
+ .nd.on.click(() => {
229
+ refs.nameInput.focus(); // Use the reference
230
+ })
231
+ ]);
232
+ ```
233
+
234
+ ## Practical Example: Simple Button with Event
235
+
236
+ ```javascript
237
+ const count = Observable(0);
238
+
239
+ const incrementButton = Button({
240
+ class: "btn btn-primary",
241
+ type: "button"
242
+ }, "Increment")
243
+ .nd.on.click(() => {
244
+ count.set(count.val() + 1);
245
+ });
246
+
247
+ const display = Div({ class: "counter-display" }, [
248
+ P("Current count: "),
249
+ Strong(count) // Reactive display
250
+ ]);
251
+
252
+ const app = Div({ class: "counter-app" }, [
253
+ display,
254
+ incrementButton
255
+ ]);
256
+ ```
257
+
258
+ ## Practical Example: Form with Validation
259
+
260
+ ```javascript
261
+ const formData = Observable.object({
262
+ name: "",
263
+ email: "",
264
+ age: ""
265
+ });
266
+
267
+ const errors = Observable.object({
268
+ name: "",
269
+ email: "",
270
+ age: ""
271
+ });
272
+
273
+ // Validation function
274
+ const validateForm = () => {
275
+ const data = formData.$val();
276
+ const newErrors = {};
277
+
278
+ newErrors.name = data.name.length < 2 ? "Name must be at least 2 characters" : "";
279
+ newErrors.email = !data.email.includes("@") ? "Invalid email address" : "";
280
+ newErrors.age = isNaN(data.age) || data.age < 1 ? "Age must be a valid number" : "";
281
+
282
+ Observable.update(errors, newErrors);
283
+
284
+ return Object.values(newErrors).every(error => error === "");
285
+ };
286
+
287
+ const contactForm = Form({ class: "contact-form" }, [
288
+ // Name field
289
+ Div({ class: "field" }, [
290
+ Label("Name:"),
291
+ Input({
292
+ type: "text",
293
+ value: formData.name,
294
+ placeholder: "Enter your name"
295
+ }).nd.on.blur(validateForm),
296
+
297
+ ShowIf(errors.name.check(err => err !== ""),
298
+ Span({ class: "error" }, errors.name)
299
+ )
300
+ ]),
301
+
302
+ // Email field
303
+ Div({ class: "field" }, [
304
+ Label("Email:"),
305
+ Input({
306
+ type: "email",
307
+ value: formData.email,
308
+ placeholder: "Enter your email"
309
+ }).nd.on.blur(validateForm),
310
+
311
+ ShowIf(errors.email.check(err => err !== ""),
312
+ Span({ class: "error" }, errors.email)
313
+ )
314
+ ]),
315
+
316
+ // Age field
317
+ Div({ class: "field" }, [
318
+ Label("Age:"),
319
+ Input({
320
+ type: "number",
321
+ value: formData.age,
322
+ placeholder: "Enter your age"
323
+ }).nd.on.blur(validateForm),
324
+
325
+ ShowIf(errors.age.check(err => err !== ""),
326
+ Span({ class: "error" }, errors.age)
327
+ )
328
+ ]),
329
+
330
+ // Submit button
331
+ Button({
332
+ type: "submit",
333
+ class: "btn btn-primary"
334
+ }, "Submit")
335
+ ])
336
+ .nd.on.prevent.submit(() => {
337
+ if (validateForm()) {
338
+ console.log("Form is valid!", formData.$val());
339
+ // Handle successful submission
340
+ } else {
341
+ console.log("Form has errors");
342
+ }
343
+ });
344
+ ```
345
+
346
+ ## Available Elements
347
+
348
+ NativeDocument provides functions for all standard HTML elements:
349
+
350
+ **Text Elements:** `H1`, `H2`, `H3`, `H4`, `H5`, `H6`, `P`, `Span`, `Strong`, `Em`, `Small`, `Mark`
351
+
352
+ **Layout Elements:** `Div`, `Section`, `Article`, `Aside`, `Header`, `Footer`, `Nav`, `Main`
353
+
354
+ **Form Elements:** `Form`, `Input`, `TextArea`, `Select`, `Option`, `Button`, `Label`, `FieldSet`, `Legend`
355
+
356
+ **List Elements:** `Ul`, `Ol`, `Li`, `Dl`, `Dt`, `Dd`
357
+
358
+ **Media Elements:** `Img`, `Audio`, `Video`, `Canvas`, `Svg`
359
+
360
+ **Interactive Elements:** `Link`, `Details`, `Summary`, `Dialog`, `Menu`
361
+
362
+ And many more following the same naming pattern!
363
+
364
+ ## Best Practices
365
+
366
+ 1. **Use semantic HTML elements** for better accessibility
367
+ 2. **Leverage reactive attributes** with observables for dynamic UIs
368
+ 3. **Group related elements** in logical containers
369
+ 4. **Use the `.nd` API** for event handling and lifecycle management
370
+ 5. **Validate form data** reactively for better user experience
371
+ 6. **Store element references** when you need to manipulate them later
372
+ 7. **Use conditional rendering** with `ShowIf` for dynamic content
373
+
374
+ ## Next Steps
375
+
376
+ Now that you understand NativeDocument's elements, explore these advanced topics:
377
+
378
+ - **[Conditional Rendering](docs/conditional-rendering.md)** - Dynamic content
379
+ - **[Routing](docs/routing.md)** - Navigation and URL management
380
+ - **[State Management](docs/state-management.md)** - Global state patterns
381
+ - **[Lifecycle Events](docs/lifecycle-events.md)** - Lifecycle events
382
+ - **[Memory Management](docs/memory-management.md)** - Memory management
383
+ - **[Anchor](docs/anchor.md)** - Anchor