mirror of
				https://github.com/jaandrle/deka-dom-el
				synced 2025-10-27 20:27:04 +01:00 
			
		
		
		
	Compare commits
	
		
			23 Commits
		
	
	
		
			969dfc5ee2
			...
			v0.9.3-alp
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 5076771410 | |||
| f0dfdfde54 | |||
| 25d475ec04 | |||
| e1f321004d | |||
| 47c5fda8d6 | |||
| 7f3b818fa5 | |||
| d742d960ac | |||
| d56d5e45d5 | |||
| 4366027658 | |||
| dba4e93b88 | |||
| 72227a80df | |||
| b347bdffc1 | |||
| e884f871b0 | |||
| c391c6549b | |||
| 091546aaab | |||
| eef4e8dfa6 | |||
| b50f8449aa | |||
| eb9139e326 | |||
| 0f91166811 | |||
| e157d2843e | |||
| 25ae6d44fe | |||
| 0ea5234a4b | |||
| 9faa24b7b3 | 
							
								
								
									
										26
									
								
								.editorconfig
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								.editorconfig
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | |||||||
|  | root = true | ||||||
|  |  | ||||||
|  | [*] | ||||||
|  | charset = utf-8 | ||||||
|  | end_of_line = lf | ||||||
|  | indent_style = tab | ||||||
|  | trim_trailing_whitespace = true | ||||||
|  | max_line_length = 120 | ||||||
|  |  | ||||||
|  | [*.json] | ||||||
|  | max_line_length = unset | ||||||
|  |  | ||||||
|  | [*.yml] | ||||||
|  | indent_style = space | ||||||
|  | indent_size = 2 | ||||||
|  |  | ||||||
|  | [*.md] | ||||||
|  | trim_trailing_whitespace = false | ||||||
|  |  | ||||||
|  | [LICENSE] | ||||||
|  | max_line_length = unset | ||||||
|  |  | ||||||
|  | [dist/**] | ||||||
|  | indent_style = unset | ||||||
|  | max_line_length = unset | ||||||
|  | trim_trailing_whitespace = unset | ||||||
							
								
								
									
										40
									
								
								.github/ISSUE_TEMPLATE/bug_report.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								.github/ISSUE_TEMPLATE/bug_report.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,40 @@ | |||||||
|  | --- | ||||||
|  | name: Bug report | ||||||
|  | about: Create a report to help us improve | ||||||
|  | title: ":bug: " | ||||||
|  | labels: bug | ||||||
|  | assignees: '' | ||||||
|  | --- | ||||||
|  |  | ||||||
|  | ## Bug Description | ||||||
|  | <!-- A clear and concise description of what the bug is --> | ||||||
|  |  | ||||||
|  | ## Steps to Reproduce | ||||||
|  | <!-- Steps to reproduce the behavior --> | ||||||
|  | 1.  | ||||||
|  | 2.  | ||||||
|  | 3.  | ||||||
|  |  | ||||||
|  | ## Expected Behavior | ||||||
|  | <!-- A clear and concise description of what you expected to happen --> | ||||||
|  |  | ||||||
|  | ## Actual Behavior | ||||||
|  | <!-- A clear and concise description of what actually happened --> | ||||||
|  |  | ||||||
|  | ## Code Sample | ||||||
|  | <!-- If applicable, add minimal code sample to reproduce the issue --> | ||||||
|  | ```js | ||||||
|  | // Your code here | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | ## Environment | ||||||
|  | - Browser and version: <!-- e.g. Chrome 120, Firefox 120, Safari 17 --> | ||||||
|  | - OS: <!-- e.g. Windows 11, macOS Sonoma, Ubuntu 22.04 --> | ||||||
|  | - dd<el> version: <!-- e.g. 0.9.2 --> | ||||||
|  | - Other relevant details: | ||||||
|  |  | ||||||
|  | ## Screenshots | ||||||
|  | <!-- If applicable, add screenshots to help explain your problem --> | ||||||
|  |  | ||||||
|  | ## Additional Context | ||||||
|  | <!-- Add any other context about the problem here --> | ||||||
							
								
								
									
										22
									
								
								.github/ISSUE_TEMPLATE/documentation.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								.github/ISSUE_TEMPLATE/documentation.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,22 @@ | |||||||
|  | --- | ||||||
|  | name: Documentation improvement | ||||||
|  | about: Suggest improvements to the documentation | ||||||
|  | title: ":abc: " | ||||||
|  | labels: documentation | ||||||
|  | assignees: '' | ||||||
|  | --- | ||||||
|  |  | ||||||
|  | ## Documentation Area | ||||||
|  | <!-- Which part of the documentation needs improvement? Provide links if applicable --> | ||||||
|  |  | ||||||
|  | ## Current Issue | ||||||
|  | <!-- What's currently unclear, missing, or incorrect in the documentation? --> | ||||||
|  |  | ||||||
|  | ## Suggested Improvement | ||||||
|  | <!-- Describe the improvement or addition you'd like to see --> | ||||||
|  |  | ||||||
|  | ## Example Content | ||||||
|  | <!-- If applicable, provide example content or wording --> | ||||||
|  |  | ||||||
|  | ## Additional Context | ||||||
|  | <!-- Any other context or screenshots about the documentation request --> | ||||||
							
								
								
									
										29
									
								
								.github/ISSUE_TEMPLATE/feature_request.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								.github/ISSUE_TEMPLATE/feature_request.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,29 @@ | |||||||
|  | --- | ||||||
|  | name: Feature request | ||||||
|  | about: Suggest an idea for this project | ||||||
|  | title: ":zap: " | ||||||
|  | labels: enhancement | ||||||
|  | assignees: '' | ||||||
|  | --- | ||||||
|  | <!-- Consider open discussion: https://github.com/jaandrle/deka-dom-el/discussions first --> | ||||||
|  |  | ||||||
|  | ## Problem Statement | ||||||
|  | <!-- A clear and concise description of the problem this feature would solve --> | ||||||
|  |  | ||||||
|  | ## Proposed Solution | ||||||
|  | <!-- A detailed description of the feature you're suggesting --> | ||||||
|  |  | ||||||
|  | ## Use Cases | ||||||
|  | <!-- Describe specific use cases where this feature would be beneficial --> | ||||||
|  |  | ||||||
|  | ## Example Implementation | ||||||
|  | <!-- If possible, provide example code or pseudocode for how this feature might work --> | ||||||
|  | ```js | ||||||
|  | // Example code | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | ## Alternatives Considered | ||||||
|  | <!-- A description of any alternative solutions or features you've considered --> | ||||||
|  |  | ||||||
|  | ## Additional Context | ||||||
|  | <!-- Any other context, screenshots, or examples that might be helpful --> | ||||||
							
								
								
									
										39
									
								
								.github/pull_request_template.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								.github/pull_request_template.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,39 @@ | |||||||
|  | <!--  | ||||||
|  | Please use an appropriate git3moji in your PR title: https://robinpokorny.github.io/git3moji/ | ||||||
|  | Examples: | ||||||
|  | - :bug: Fix signal update not triggering on nested properties | ||||||
|  | - :zap: Improve event delegation performance | ||||||
|  | - :abc: Add documentation for custom elements | ||||||
|  | --> | ||||||
|  |  | ||||||
|  | ## Description | ||||||
|  | <!-- Describe the changes introduced by this PR --> | ||||||
|  |  | ||||||
|  | ## Related Issues | ||||||
|  | <!-- Link any related issues using the format #ISSUE_NUMBER --> | ||||||
|  |  | ||||||
|  | ## Type of Change | ||||||
|  | - [ ] Bug fix (non-breaking change that fixes an issue) | ||||||
|  | - [ ] New feature (non-breaking change that adds functionality) | ||||||
|  | - [ ] Breaking change (fix or feature that would cause existing functionality to change) | ||||||
|  | - [ ] Documentation update | ||||||
|  | - [ ] Code refactoring | ||||||
|  | - [ ] Performance improvement | ||||||
|  | - [ ] Test update | ||||||
|  |  | ||||||
|  | ## Testing Performed | ||||||
|  | <!-- Describe the tests you've done to verify your changes --> | ||||||
|  |  | ||||||
|  | ## Screenshots | ||||||
|  | <!-- If applicable, add screenshots to help explain your changes --> | ||||||
|  |  | ||||||
|  | ## Checklist | ||||||
|  | - [ ] My code follows the code style of this project | ||||||
|  | - [ ] I have performed a self-review of my own code | ||||||
|  | - [ ] I have added tests that prove my fix is effective or that my feature works | ||||||
|  | - [ ] I have updated the documentation accordingly | ||||||
|  | - [ ] My changes generate no new warnings | ||||||
|  | - [ ] All existing tests are passing | ||||||
|  |  | ||||||
|  | ## Additional Notes | ||||||
|  | <!-- Any additional information that might be helpful for reviewers --> | ||||||
							
								
								
									
										18
									
								
								.github/workflows/npm-publish.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								.github/workflows/npm-publish.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,18 @@ | |||||||
|  | name: Publish Package to npmjs | ||||||
|  | on: | ||||||
|  |   workflow_dispatch: | ||||||
|  |   release: | ||||||
|  |     types: [created] | ||||||
|  | jobs: | ||||||
|  |   build: | ||||||
|  |     runs-on: ubuntu-latest | ||||||
|  |     steps: | ||||||
|  |       - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 | ||||||
|  |       - uses: actions/setup-node@cdca7365b2dadb8aad0a33bc7601856ffabcc48e # v4.3.0 | ||||||
|  |         with: | ||||||
|  |           node-version: '20.16' | ||||||
|  |           registry-url: 'https://registry.npmjs.org' | ||||||
|  |       - run: npm ci | ||||||
|  |       - run: npm publish | ||||||
|  |         env: | ||||||
|  |           NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} | ||||||
							
								
								
									
										23
									
								
								.github/workflows/pr.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								.github/workflows/pr.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,23 @@ | |||||||
|  | # https://nektosact.com/usage/index.html | ||||||
|  | # https://github.com/reviewdog/action-eclint | ||||||
|  | name: On PR | ||||||
|  | on: | ||||||
|  |   workflow_dispatch: | ||||||
|  |   pull_request: | ||||||
|  |     branches: [main] | ||||||
|  |  | ||||||
|  | jobs: | ||||||
|  |   pr: | ||||||
|  |     name: Validates formatting and linting | ||||||
|  |     runs-on: ubuntu-latest | ||||||
|  |     steps: | ||||||
|  |       - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 | ||||||
|  |       - uses: reviewdog/action-eclint@d51e853275e707b64c0526881ada324f454c1110 # v1.7.1 | ||||||
|  |         with: | ||||||
|  |           reporter: github-pr-check | ||||||
|  |           eclint_flags: '--fix' | ||||||
|  |       - uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0 | ||||||
|  |         with: | ||||||
|  |           node-version: 20.16 | ||||||
|  |       - run: npm ci | ||||||
|  |       - run: bs/lint.sh | ||||||
							
								
								
									
										48
									
								
								.github/workflows/static.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								.github/workflows/static.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,48 @@ | |||||||
|  | # Simple workflow for deploying static content to GitHub Pages | ||||||
|  | name: Deploy Docs | ||||||
|  |  | ||||||
|  | on: | ||||||
|  |   # Runs on pushes targeting the default branch | ||||||
|  |   push: | ||||||
|  |     branches: ["main"] | ||||||
|  |  | ||||||
|  |   # Allows you to run this workflow manually from the Actions tab | ||||||
|  |   workflow_dispatch: | ||||||
|  |  | ||||||
|  | # Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages | ||||||
|  | permissions: | ||||||
|  |   contents: read | ||||||
|  |   pages: write | ||||||
|  |   id-token: write | ||||||
|  |  | ||||||
|  | # Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued. | ||||||
|  | # However, do NOT cancel in-progress runs as we want to allow these production deployments to complete. | ||||||
|  | concurrency: | ||||||
|  |   group: "pages" | ||||||
|  |   cancel-in-progress: false | ||||||
|  |  | ||||||
|  | jobs: | ||||||
|  |   # Single deploy job since we're just deploying | ||||||
|  |   deploy: | ||||||
|  |     environment: | ||||||
|  |       name: github-pages | ||||||
|  |       url: ${{ steps.deployment.outputs.page_url }} | ||||||
|  |     runs-on: ubuntu-latest | ||||||
|  |     steps: | ||||||
|  |       - name: Checkout | ||||||
|  |         uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 | ||||||
|  |       - uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0 | ||||||
|  |         with: | ||||||
|  |           node-version: 20.16 | ||||||
|  |       - run: npm ci | ||||||
|  |       - run: bs/docs.js | ||||||
|  |       - name: Setup Pages | ||||||
|  |         uses: actions/configure-pages@983d7736d9b0ae728b81ab479565c72886d7745b # v5 | ||||||
|  |       - name: Upload artifact | ||||||
|  |         uses: actions/upload-pages-artifact@56afc609e74202658d3ffba0e8f6dda462b719fa # v3 | ||||||
|  |         with: | ||||||
|  |           # Upload entire repository | ||||||
|  |           path: './dist/docs' | ||||||
|  |       - name: Deploy to GitHub Pages | ||||||
|  |         id: deployment | ||||||
|  |         uses: actions/deploy-pages@d6db90164ac5ed86f2b6aed7e0febac5b3c0c03e # v4 | ||||||
							
								
								
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -1,3 +1,5 @@ | |||||||
|  | dist/docs/ | ||||||
|  | dist/.* | ||||||
| # Logs | # Logs | ||||||
| logs | logs | ||||||
| *.log | *.log | ||||||
|   | |||||||
							
								
								
									
										3
									
								
								.npmrc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								.npmrc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | |||||||
|  | //registry.npmjs.org/:_authToken=${NODE_AUTH_TOKEN} | ||||||
|  | registry=https://registry.npmjs.org/ | ||||||
|  | always-auth=true | ||||||
							
								
								
									
										134
									
								
								CODE_OF_CONDUCT.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										134
									
								
								CODE_OF_CONDUCT.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,134 @@ | |||||||
|  |  | ||||||
|  | # Contributor Covenant Code of Conduct | ||||||
|  |  | ||||||
|  | ## Our Pledge | ||||||
|  |  | ||||||
|  | We as members, contributors, and leaders pledge to make participation in our | ||||||
|  | community a harassment-free experience for everyone, regardless of age, body | ||||||
|  | size, visible or invisible disability, ethnicity, sex characteristics, gender | ||||||
|  | identity and expression, level of experience, education, socio-economic status, | ||||||
|  | nationality, personal appearance, race, caste, color, religion, or sexual | ||||||
|  | identity and orientation. | ||||||
|  |  | ||||||
|  | We pledge to act and interact in ways that contribute to an open, welcoming, | ||||||
|  | diverse, inclusive, and healthy community. | ||||||
|  |  | ||||||
|  | ## Our Standards | ||||||
|  |  | ||||||
|  | Examples of behavior that contributes to a positive environment for our | ||||||
|  | community include: | ||||||
|  |  | ||||||
|  | * Demonstrating empathy and kindness toward other people | ||||||
|  | * Being respectful of differing opinions, viewpoints, and experiences | ||||||
|  | * Giving and gracefully accepting constructive feedback | ||||||
|  | * Accepting responsibility and apologizing to those affected by our mistakes, | ||||||
|  | 	and learning from the experience | ||||||
|  | * Focusing on what is best not just for us as individuals, but for the overall | ||||||
|  | 	community | ||||||
|  |  | ||||||
|  | Examples of unacceptable behavior include: | ||||||
|  |  | ||||||
|  | * The use of sexualized language or imagery, and sexual attention or advances of | ||||||
|  | 	any kind | ||||||
|  | * Trolling, insulting or derogatory comments, and personal or political attacks | ||||||
|  | * Public or private harassment | ||||||
|  | * Publishing others' private information, such as a physical or email address, | ||||||
|  | 	without their explicit permission | ||||||
|  | * Other conduct which could reasonably be considered inappropriate in a | ||||||
|  | 	professional setting | ||||||
|  |  | ||||||
|  | ## Enforcement Responsibilities | ||||||
|  |  | ||||||
|  | Community leaders are responsible for clarifying and enforcing our standards of | ||||||
|  | acceptable behavior and will take appropriate and fair corrective action in | ||||||
|  | response to any behavior that they deem inappropriate, threatening, offensive, | ||||||
|  | or harmful. | ||||||
|  |  | ||||||
|  | Community leaders have the right and responsibility to remove, edit, or reject | ||||||
|  | comments, commits, code, wiki edits, issues, and other contributions that are | ||||||
|  | not aligned to this Code of Conduct, and will communicate reasons for moderation | ||||||
|  | decisions when appropriate. | ||||||
|  |  | ||||||
|  | ## Scope | ||||||
|  |  | ||||||
|  | This Code of Conduct applies within all community spaces, and also applies when | ||||||
|  | an individual is officially representing the community in public spaces. | ||||||
|  | Examples of representing our community include using an official e-mail address, | ||||||
|  | posting via an official social media account, or acting as an appointed | ||||||
|  | representative at an online or offline event. | ||||||
|  |  | ||||||
|  | ## Enforcement | ||||||
|  |  | ||||||
|  | Instances of abusive, harassing, or otherwise unacceptable behavior may be | ||||||
|  | reported to the community leaders responsible for enforcement at | ||||||
|  | andrle.jan@centrum.cz. | ||||||
|  | All complaints will be reviewed and investigated promptly and fairly. | ||||||
|  |  | ||||||
|  | All community leaders are obligated to respect the privacy and security of the | ||||||
|  | reporter of any incident. | ||||||
|  |  | ||||||
|  | ## Enforcement Guidelines | ||||||
|  |  | ||||||
|  | Community leaders will follow these Community Impact Guidelines in determining | ||||||
|  | the consequences for any action they deem in violation of this Code of Conduct: | ||||||
|  |  | ||||||
|  | ### 1. Correction | ||||||
|  |  | ||||||
|  | **Community Impact**: Use of inappropriate language or other behavior deemed | ||||||
|  | unprofessional or unwelcome in the community. | ||||||
|  |  | ||||||
|  | **Consequence**: A private, written warning from community leaders, providing | ||||||
|  | clarity around the nature of the violation and an explanation of why the | ||||||
|  | behavior was inappropriate. A public apology may be requested. | ||||||
|  |  | ||||||
|  | ### 2. Warning | ||||||
|  |  | ||||||
|  | **Community Impact**: A violation through a single incident or series of | ||||||
|  | actions. | ||||||
|  |  | ||||||
|  | **Consequence**: A warning with consequences for continued behavior. No | ||||||
|  | interaction with the people involved, including unsolicited interaction with | ||||||
|  | those enforcing the Code of Conduct, for a specified period of time. This | ||||||
|  | includes avoiding interactions in community spaces as well as external channels | ||||||
|  | like social media. Violating these terms may lead to a temporary or permanent | ||||||
|  | ban. | ||||||
|  |  | ||||||
|  | ### 3. Temporary Ban | ||||||
|  |  | ||||||
|  | **Community Impact**: A serious violation of community standards, including | ||||||
|  | sustained inappropriate behavior. | ||||||
|  |  | ||||||
|  | **Consequence**: A temporary ban from any sort of interaction or public | ||||||
|  | communication with the community for a specified period of time. No public or | ||||||
|  | private interaction with the people involved, including unsolicited interaction | ||||||
|  | with those enforcing the Code of Conduct, is allowed during this period. | ||||||
|  | Violating these terms may lead to a permanent ban. | ||||||
|  |  | ||||||
|  | ### 4. Permanent Ban | ||||||
|  |  | ||||||
|  | **Community Impact**: Demonstrating a pattern of violation of community | ||||||
|  | standards, including sustained inappropriate behavior, harassment of an | ||||||
|  | individual, or aggression toward or disparagement of classes of individuals. | ||||||
|  |  | ||||||
|  | **Consequence**: A permanent ban from any sort of public interaction within the | ||||||
|  | community. | ||||||
|  |  | ||||||
|  | ## Attribution | ||||||
|  |  | ||||||
|  | This Code of Conduct is adapted from the [Contributor Covenant][homepage], | ||||||
|  | version 2.1, available at | ||||||
|  | [https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1]. | ||||||
|  |  | ||||||
|  | Community Impact Guidelines were inspired by | ||||||
|  | [Mozilla's code of conduct enforcement ladder][Mozilla CoC]. | ||||||
|  |  | ||||||
|  | For answers to common questions about this code of conduct, see the FAQ at | ||||||
|  | [https://www.contributor-covenant.org/faq][FAQ]. Translations are available at | ||||||
|  | [https://www.contributor-covenant.org/translations][translations]. | ||||||
|  |  | ||||||
|  | [homepage]: https://www.contributor-covenant.org | ||||||
|  | [v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html | ||||||
|  | [Mozilla CoC]: https://github.com/mozilla/diversity | ||||||
|  | [FAQ]: https://www.contributor-covenant.org/faq | ||||||
|  | [translations]: https://www.contributor-covenant.org/translations | ||||||
|  |  | ||||||
							
								
								
									
										174
									
								
								CONTRIBUTING.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										174
									
								
								CONTRIBUTING.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,174 @@ | |||||||
|  | # Contributing to Deka DOM Elements | ||||||
|  |  | ||||||
|  | Thank you for your interest in contributing to Deka DOM Elements (dd<el> or DDE)! This document provides guidelines and | ||||||
|  | instructions for contributing to the project. | ||||||
|  |  | ||||||
|  | ## Table of Contents | ||||||
|  |  | ||||||
|  | - [Code of Conduct](#code-of-conduct) | ||||||
|  | - [Getting Started](#getting-started) | ||||||
|  | - [Development Workflow](#development-workflow) | ||||||
|  | - [Commit Guidelines](#commit-guidelines) | ||||||
|  | - [Pull Request Process](#pull-request-process) | ||||||
|  | - [Issue Guidelines](#issue-guidelines) | ||||||
|  | - [Coding Standards](#coding-standards) | ||||||
|  | - [Testing](#testing) | ||||||
|  | - [Documentation](#documentation) | ||||||
|  |  | ||||||
|  | ## Code of Conduct | ||||||
|  |  | ||||||
|  | Please be respectful and inclusive in your interactions with other contributors. We aim to foster a welcoming community | ||||||
|  | where everyone feels comfortable participating. | ||||||
|  |  | ||||||
|  | ## Getting Started | ||||||
|  |  | ||||||
|  | 1. **Fork the repository**: | ||||||
|  | 	- Click the "Fork" button on the GitHub repository | ||||||
|  |  | ||||||
|  | 2. **Clone your fork**: | ||||||
|  | 	```bash | ||||||
|  | 	git clone https://github.com/YOUR-USERNAME/deka-dom-el.git | ||||||
|  | 	cd deka-dom-el | ||||||
|  | 	``` | ||||||
|  |  | ||||||
|  | 3. **Set up the development environment**: | ||||||
|  | 	```bash | ||||||
|  | 	npm ci | ||||||
|  | 	``` | ||||||
|  |  | ||||||
|  | 4. **Add the upstream repository**: | ||||||
|  | 	```bash | ||||||
|  | 	git remote add upstream https://github.com/jaandrle/deka-dom-el.git | ||||||
|  | 	``` | ||||||
|  |  | ||||||
|  | ## Development Workflow | ||||||
|  |  | ||||||
|  | 1. **Create a new branch**: | ||||||
|  | 	```bash | ||||||
|  | 	git checkout -b your-feature-branch | ||||||
|  | 	``` | ||||||
|  | 	Use descriptive branch names that reflect the changes you're making. | ||||||
|  |  | ||||||
|  | 2. **Make your changes**: | ||||||
|  | 	- Write clean, modular code | ||||||
|  | 	- Follow the project's coding standards (see [Coding Standards](#coding-standards)) | ||||||
|  | 	- Include relevant tests for your changes | ||||||
|  |  | ||||||
|  | 3. ~**Run tests**:~ | ||||||
|  | 	```bash | ||||||
|  | 	#npm test | ||||||
|  | 	``` | ||||||
|  |  | ||||||
|  | 4. **Build the project**: | ||||||
|  | 	```bash | ||||||
|  | 	npm run build | ||||||
|  | 	#or | ||||||
|  | 	bs/build.js | ||||||
|  | 	``` | ||||||
|  |  | ||||||
|  | 5. **Preview documentation changes** (if applicable): | ||||||
|  | 	```bash | ||||||
|  | 	npm run docs | ||||||
|  | 	#or | ||||||
|  | 	bs/docs.js | ||||||
|  | 	``` | ||||||
|  |  | ||||||
|  | …see [BS folder](./bs/README.md) for more info. | ||||||
|  |  | ||||||
|  | ## Commit Guidelines | ||||||
|  |  | ||||||
|  | We use | ||||||
|  | [](https://robinpokorny.github.io/git3moji/) <!-- editorconfig-checker-disable-line --> | ||||||
|  | for commit messages. This helps keep the commit history clear and consistent. | ||||||
|  |  | ||||||
|  | ``` | ||||||
|  | :emoji: Short summary of the change | ||||||
|  | ``` | ||||||
|  | …for example: | ||||||
|  |  | ||||||
|  | ``` | ||||||
|  | :bug: Fix signal update not triggering on nested properties | ||||||
|  | :zap: Improve event delegation performance | ||||||
|  | :abc: Add documentation for custom elements | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | ## Pull Request Process | ||||||
|  |  | ||||||
|  | 1. **Push your changes**: | ||||||
|  | 	```bash | ||||||
|  | 	git push origin your-feature-branch | ||||||
|  | 	``` | ||||||
|  |  | ||||||
|  | 2. **Open a Pull Request**: | ||||||
|  | 	- Go to the repository on GitHub | ||||||
|  | 	- Click "New Pull Request" | ||||||
|  | 	- Select your branch | ||||||
|  | 	- Provide a clear description of your changes | ||||||
|  |  | ||||||
|  | 3. **PR Guidelines**: | ||||||
|  | 	- Use a clear, descriptive title with the appropriate git3moji | ||||||
|  | 	- Reference any related issues | ||||||
|  | 	- Explain what the changes do and why they are needed | ||||||
|  | 	- List any dependencies that are required for the change | ||||||
|  | 	- Include screenshots or examples if applicable | ||||||
|  |  | ||||||
|  | 4. **Code Review**: | ||||||
|  | 	- Address any feedback from reviewers | ||||||
|  | 	- Make necessary changes and push to your branch | ||||||
|  | 	- The PR will be updated automatically | ||||||
|  |  | ||||||
|  | 5. **Merge**: | ||||||
|  | 	- Once approved, a maintainer will merge your PR | ||||||
|  | 	- The main branch is protected, so you cannot push directly to it | ||||||
|  |  | ||||||
|  | ## Issue Guidelines | ||||||
|  |  | ||||||
|  | When creating an issue, please use the appropriate template and include as much information as possible: | ||||||
|  |  | ||||||
|  | ### Bug Reports | ||||||
|  |  | ||||||
|  | - Use the `:bug:` emoji in the title | ||||||
|  | - Clearly describe the issue | ||||||
|  | - Include steps to reproduce | ||||||
|  | - Mention your environment (browser, OS, etc.) | ||||||
|  | - Add screenshots if applicable | ||||||
|  |  | ||||||
|  | ### Feature Requests | ||||||
|  |  | ||||||
|  | - Use the `:zap:` emoji in the title | ||||||
|  | - Describe the feature clearly | ||||||
|  | - Explain why it would be valuable | ||||||
|  | - Include examples or mockups if possible | ||||||
|  |  | ||||||
|  | ### Documentation Improvements | ||||||
|  |  | ||||||
|  | - Use the `:abc:` emoji in the title | ||||||
|  | - Identify what documentation needs improvement | ||||||
|  | - Suggest specific changes or additions | ||||||
|  |  | ||||||
|  | ## Coding Standards | ||||||
|  |  | ||||||
|  | - Follow the existing code style in the project | ||||||
|  | - Use meaningful variable and function names | ||||||
|  | - Keep functions small and focused | ||||||
|  | - Add comments for complex logic | ||||||
|  | - Use TypeScript types appropriately | ||||||
|  |  | ||||||
|  | <!-- | ||||||
|  | ## Testing | ||||||
|  |  | ||||||
|  | - Add tests for new features | ||||||
|  | - Update tests for modified code | ||||||
|  | - Ensure all tests pass before submitting a PR | ||||||
|  | --> | ||||||
|  |  | ||||||
|  | ## Documentation | ||||||
|  |  | ||||||
|  | - Update the documentation when you add or modify features | ||||||
|  | - Document both API usage and underlying concepts | ||||||
|  | - Use clear, concise language | ||||||
|  | - Include examples where appropriate | ||||||
|  |  | ||||||
|  | --- | ||||||
|  |  | ||||||
|  | Thank you for contributing to Deka DOM Elements! Your efforts help make the project better for everyone. | ||||||
							
								
								
									
										191
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										191
									
								
								README.md
									
									
									
									
									
								
							| @@ -1,80 +1,149 @@ | |||||||
| **WIP** (the experimentation phase) | [source code on GitHub](https://github.com/jaandrle/deka-dom-el) | [*mirrored* on Gitea](https://gitea.jaandrle.cz/jaandrle/deka-dom-el) | **Alpha** | ||||||
|  | | [source code on GitHub](https://github.com/jaandrle/deka-dom-el) | ||||||
|  | | [*mirrored* on Gitea](https://gitea.jaandrle.cz/jaandrle/deka-dom-el) | ||||||
|  | | [](https://robinpokorny.github.io/git3moji/) <!-- editorconfig-checker-disable-line --> | ||||||
|  |  | ||||||
|  | <p align="center"> | ||||||
|  | 	<img src="docs/assets/logo.svg" alt="Deka DOM Elements Logo" width="180" height="180"> | ||||||
|  | </p> | ||||||
|  |  | ||||||
|  | # Deka DOM Elements (dd\<el\> or DDE) | ||||||
|  |  | ||||||
| ***Vanilla for flavouring — a full-fledged feast for large projects*** | ***Vanilla for flavouring — a full-fledged feast for large projects*** | ||||||
|  |  | ||||||
| *…use simple DOM API by default and library tools and logic when you need them* | *…use simple DOM API by default and library tools and logic when you need them* | ||||||
|  |  | ||||||
| ```js | ```javascript | ||||||
|  | // 🌟 Reactive component with clear separation of concerns | ||||||
| document.body.append( | document.body.append( | ||||||
| 	el("h1", "Hello World 👋"), | 	el(EmojiCounter, { initial: "🚀" }) | ||||||
| 	el("p", "See some syntax examples here:"), |  | ||||||
| 	el("ul").append( |  | ||||||
| 		el("li").append( |  | ||||||
| 			el("a", { textContent: "Link to the library repo", title: "Deka DOM El — GitHub", href: "https://github.com/jaandrle/deka-dom-el" }) |  | ||||||
| 		), |  | ||||||
| 		el("li").append( |  | ||||||
| 			"Use extended Vanilla JavaScript DOM/IDL API: ", |  | ||||||
| 			el("span", { textContent: "» this is a span with class=cN and data-a=A, data-b=B «", className: "cN", dataset: { a: "A", b: "B" } }) |  | ||||||
| 		), |  | ||||||
| 		el("li").append( |  | ||||||
| 			el(component, { textContent: "A component", className: "example" }, on("change", console.log)) |  | ||||||
| 		) |  | ||||||
| 	) |  | ||||||
| 	 |  | ||||||
| ); | ); | ||||||
| function component({ textContent, className }){ |  | ||||||
| 	const value= S("onchange"); | function EmojiCounter({ initial }) { | ||||||
| 	 | 	// ✨ State - Define reactive data | ||||||
|  | 	const count = S(0); | ||||||
|  | 	const emoji = S(initial); | ||||||
|  |  | ||||||
|  | 	/** @param {HTMLOptionElement} el */ | ||||||
|  | 	const isSelected= el=> (el.selected= el.value===initial); | ||||||
|  |  | ||||||
|  | 	// 🔄 View - UI updates automatically when signals change | ||||||
| 	return el().append( | 	return el().append( | ||||||
| 		el("p", { textContent, className }), | 		el("p", { | ||||||
| 		el("p", { className: [ className, "second-line" ] }).append( | 			className: "output", | ||||||
| 			"…with reactivity: ", el("em", { style: { fontWeight: "bold" }, ariaset: { live: "polite" }, textContent: value }), | 			textContent: S(() => | ||||||
|  | 				`Hello World ${emoji.get().repeat(count.get())}`), | ||||||
|  | 		}), | ||||||
|  |  | ||||||
|  | 		// 🎮 Controls - Update state on events | ||||||
|  | 		el("button", { textContent: "Add Emoji" }, | ||||||
|  | 			on("click", () => count.set(count.get() + 1)) | ||||||
| 		), | 		), | ||||||
| 		el("input", { type: "text", value: value() }, on("change", event=> value(event.target.value))) |  | ||||||
|  | 		el("select", null, on.defer(el=> el.value= initial), | ||||||
|  | 			on("change", e => emoji.set(e.target.value)) | ||||||
|  | 		).append( | ||||||
|  | 			el(Option, "🎉"), | ||||||
|  | 			el(Option, "🚀"), | ||||||
|  | 			el(Option, "💖"), | ||||||
|  | 		) | ||||||
| 	); | 	); | ||||||
| } | } | ||||||
|  | function Option({ textContent }){ | ||||||
|  | 	return el("option", { value: textContent, textContent }); | ||||||
|  | } | ||||||
| ``` | ``` | ||||||
| # Deka DOM Elements |  | ||||||
| Creating reactive elements, components and Web components using [IDL](https://developer.mozilla.org/en-US/docs/Glossary/IDL)/JavaScript DOM API and [**signals/observables**](#signals). |  | ||||||
|  |  | ||||||
| ## Inspiration and suggested alternatives | Creating reactive elements, components, and Web Components using the native | ||||||
| - my previous library (mostly used internaly): [jaandrle/dollar_dom_component: Functional DOM components without JSX and virtual DOM.](https://github.com/jaandrle/dollar_dom_component) | [IDL](https://developer.mozilla.org/en-US/docs/Glossary/IDL)/JavaScript DOM API enhanced with | ||||||
| - [vanjs-org/van: 🍦 VanJS: World's smallest reactive UI framework. Incredibly Powerful, Insanely Small - Everyone can build a useful UI app in an hour.](https://github.com/vanjs-org/van) | [**signals/observables**](#understanding-signals). | ||||||
| - [hyperhype/hyperscript: Create HyperText with JavaScript.](https://github.com/hyperhype/hyperscript) |  | ||||||
| - [adamhaile/S: S.js - Simple, Clean, Fast Reactive Programming in Javascript](https://github.com/adamhaile/S) ([adamhaile/surplus: High performance JSX web views for S.js applications](https://github.com/adamhaile/surplus)) |  | ||||||
| - [potch/signals: a small reactive signals library](https://github.com/potch/signals) |  | ||||||
|  |  | ||||||
| ## Why an another one? | ## Features at a Glance | ||||||
| This library falls somewhere between van/hyperscript and [solid-js](https://github.com/solidjs/solid) in terms of size, complexity, |  | ||||||
| and usability. |  | ||||||
|  |  | ||||||
| Another goal is to proceed in the best spirit of functional programming. This involves starting with | - ✅ **No build step required** — use directly in browsers or Node.js | ||||||
| pure JavaScript (DOM API) and gradually adding auxiliary functions, ranging from “minor” improvements | - ☑️ **Lightweight** — ~10-15kB minified (original goal 10kB) with **zero**/minimal dependencies | ||||||
| to the capability of writing complete declarative reactive UI templates. | - ✅ **Declarative & functional approach** for clean, maintainable code | ||||||
|  | - ✅ **Signals and events** for reactive UI | ||||||
|  | - ✅ **Memoization for performance** — optimize rendering with intelligent caching | ||||||
|  | - ✅ **Optional build-in signals** with support for custom reactive implementations (#39) | ||||||
|  | - ✅ **Server-side rendering** support via [jsdom](https://github.com/jsdom/jsdom) | ||||||
|  | - ✅ **TypeScript support** | ||||||
|  | - ☑️ **Support for debugging with browser DevTools** without extensions | ||||||
|  | - ☑️ **Enhanced Web Components** support | ||||||
|  |  | ||||||
| As a result, any “internal” function (`assign`, `classListDeclarative`, `on`, `dispatchEvent`, …, `S`, …) | ## Getting Started | ||||||
| can be used independently, although they are primarily designed for use in combination.  This can also, |  | ||||||
| hopefully, help in integrating the library into existing projects. |  | ||||||
|  |  | ||||||
| To balance these requirements, numerous compromises have been made. To summarize: | ### Documentation | ||||||
| - [ ] Library size: 10–15kB minified (the original goal was a maximum of 10kB) |  | ||||||
| - [x] Optional use of *signals* with the ability to register *your own signals/observables implementation* |  | ||||||
| - [x] *No build step required* |  | ||||||
| - [x] Preference for a *declarative/functional* approach |  | ||||||
| - [x] Focus on zero/minimal dependencies |  | ||||||
| - [ ] Support for/enhancement of custom elements (web components) |  | ||||||
| - [x] Support for SSR ([jsdom](https://github.com/jsdom/jsdom)) |  | ||||||
| - [ ] WIP providing types |  | ||||||
|  |  | ||||||
| ## First steps | - [**Documentation and Guide**](https://jaandrle.github.io/deka-dom-el) | ||||||
| - [**Guide**](https://jaandrle.github.io/deka-dom-el) | - [**Examples**](https://jaandrle.github.io/deka-dom-el/p15-examples.html) | ||||||
| - Documentation |  | ||||||
| - Installation |  | ||||||
| 	- npm |  | ||||||
| 	- [dist/](dist/) (`https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/`…) |  | ||||||
|  |  | ||||||
| ## Signals | ### Installation | ||||||
| - [Signals — whats going on behind the scenes | by Ryan Hoffnan | ITNEXT](https://itnext.io/signals-whats-going-on-behind-the-scenes-ec858589ea63) |  | ||||||
| - [The Evolution of Signals in JavaScript - DEV Community](https://dev.to/this-is-learning/the-evolution-of-signals-in-javascript-8ob) | ```bash | ||||||
| - there is also [tc39/proposal-signals: A proposal to add signals to JavaScript.](https://github.com/tc39/proposal-signals) | npm install deka-dom-el --save | ||||||
| - [Observer pattern - Wikipedia](https://en.wikipedia.org/wiki/Observer_pattern) | ``` | ||||||
|  |  | ||||||
|  | …or via CDN / Direct Script: | ||||||
|  |  | ||||||
|  | For CDN links and various build formats (ESM/IIFE, with/without signals, minified/unminified), see the [interactive | ||||||
|  | format selector](https://jaandrle.github.io/deka-dom-el/) on the documentation site. | ||||||
|  |  | ||||||
|  | ```html | ||||||
|  | <!-- Example with IIFE build (creates a global DDE object) --> | ||||||
|  | <script src="https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/iife-with-signals.min.js"></script> | ||||||
|  | <script> | ||||||
|  | 	const { el, S } = DDE; | ||||||
|  | 	// Your code here | ||||||
|  | </script> | ||||||
|  |  | ||||||
|  | <!-- Or with ES modules --> | ||||||
|  | <script type="module"> | ||||||
|  | 	import { el, S } from "https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-signals.min.js"; | ||||||
|  | 	// Your code here | ||||||
|  | </script> | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | ## Why Another Library? | ||||||
|  |  | ||||||
|  | This library bridges the gap between minimal solutions like van/hyperscript and more comprehensive frameworks like | ||||||
|  | [solid-js](https://github.com/solidjs/solid), offering a balanced trade-off between size, complexity, and usability. | ||||||
|  |  | ||||||
|  | Following functional programming principles, dd\<el\> starts with pure JavaScript (DOM API) and gradually adds | ||||||
|  | auxiliary functions. These range from minor improvements to advanced features for building complete declarative | ||||||
|  | reactive UI templates. | ||||||
|  |  | ||||||
|  | A key advantage: any internal function (`assign`, `classListDeclarative`, `on`, `dispatchEvent`, `S`, etc.) can be used | ||||||
|  | independently while also working seamlessly together. This modular approach makes it easier to integrate the library | ||||||
|  | into existing projects. | ||||||
|  |  | ||||||
|  | ## Understanding Signals | ||||||
|  |  | ||||||
|  | Signals are the reactive backbone of Deka DOM Elements: | ||||||
|  |  | ||||||
|  | - [Signals — what's going on behind the scenes](https://itnext.io/signals-whats-going-on-behind-the-scenes-ec858589ea63) | ||||||
|  | - [The Evolution of Signals in JavaScript](https://dev.to/this-is-learning/the-evolution-of-signals-in-javascript-8ob) | ||||||
|  | - [TC39 Signals Proposal](https://github.com/tc39/proposal-signals) (future standard) | ||||||
|  | - [Observer pattern](https://en.wikipedia.org/wiki/Observer_pattern) (underlying concept) | ||||||
|  |  | ||||||
|  | ## Contributing | ||||||
|  |  | ||||||
|  | We welcome contributions from the community! Please see our [Contributing Guide](CONTRIBUTING.md) for details on how to | ||||||
|  | get started, coding standards, commit guidelines, and the pull request process. | ||||||
|  |  | ||||||
|  | ## Inspiration and Alternatives | ||||||
|  |  | ||||||
|  | - [vanjs-org/van](https://github.com/vanjs-org/van) — World's smallest reactive UI framework | ||||||
|  | - [adamhaile/S](https://github.com/adamhaile/S) — Simple, clean, fast reactive programming | ||||||
|  | - [hyperhype/hyperscript](https://github.com/hyperhype/hyperscript) — Create HyperText with JavaScript | ||||||
|  | - [potch/signals](https://github.com/potch/signals) — A small reactive signals library | ||||||
|  | - [AseasRoa/paintor](https://github.com/AseasRoa/paintor) - JavaScript library for building reactive client-side user | ||||||
|  | 	interfaces or HTML code. | ||||||
|  | - [pota](https://pota.quack.uy/) — small and pluggable Reactive Web Renderer. It's compiler-less, includes an html | ||||||
|  | 	function, and a optimized babel preset in case you fancy JSX. | ||||||
|  | - [jaandrle/dollar_dom_component](https://github.com/jaandrle/dollar_dom_component) — | ||||||
|  | 	Functional DOM components without JSX/virtual DOM | ||||||
|  | - [TarekRaafat/eleva](https://github.com/TarekRaafat/eleva) — A minimalist, lightweight, pure vanilla JavaScript | ||||||
|  | 	frontend runtime framework. | ||||||
|  | - [didi/mpx](https://github.com/didi/mpx) — Mpx,一款具有优秀开发体验和深度性能优化的增强型跨端小程序框架 | ||||||
|  | - [mxjp/rvx](https://github.com/mxjp/rvx) — A signal based frontend framework | ||||||
|   | |||||||
							
								
								
									
										20
									
								
								bs/README.md
									
									
									
									
									
								
							
							
						
						
									
										20
									
								
								bs/README.md
									
									
									
									
									
								
							| @@ -1 +1,19 @@ | |||||||
| [jaandrle/bs: The simplest possible build system using executables](https://github.com/jaandrle/bs/) | ## bs: Build system based on executables | ||||||
|  | This project uses [jaandrle/bs: The simplest possible build system using executable/bash scripts]( | ||||||
|  | https://github.com/jaandrle/bs). | ||||||
|  |  | ||||||
|  | #### bs/build.js [main|signals] [--no-types|--help] | ||||||
|  | Generates alternative versions of the project (other than native ESM code). | ||||||
|  | Also generates typescript definitions. | ||||||
|  |  | ||||||
|  | #### bs/docs.js | ||||||
|  | Generates documentation, from `docs/`. Uses “SSR” technique, using deka-dom-el itself. | ||||||
|  |  | ||||||
|  | For running use `npx serve dist/docs`. | ||||||
|  |  | ||||||
|  | #### bs/lint.sh | ||||||
|  | Lints size of the project, jshint. See configs: | ||||||
|  |  | ||||||
|  | - `package.json`: key `size-limit` | ||||||
|  | - `package.json`: key `jshintConfig` | ||||||
|  | - `.editorconfig` | ||||||
|   | |||||||
							
								
								
									
										90
									
								
								bs/build.js
									
									
									
									
									
								
							
							
						
						
									
										90
									
								
								bs/build.js
									
									
									
									
									
								
							| @@ -1,62 +1,40 @@ | |||||||
| #!/usr/bin/env -S npx nodejsscript | #!/usr/bin/env -S npx nodejsscript | ||||||
| import { bundle as bundleDTS } from "dts-bundler"; | import { build } from "./dev/.build.js" | ||||||
| const files= [ "index", "index-with-signals" ]; | const files= [ "index", "index-with-signals" ]; | ||||||
| const filesOut= (file, mark= "esm")=> "dist/"+file.replace("index", mark); |  | ||||||
| const css= echo.css` |  | ||||||
| 	.info{ color: gray; } |  | ||||||
| `; |  | ||||||
|  |  | ||||||
| $.api("", true) | $.api("") | ||||||
| .option("--minify", "Level of minification [ full, partial (default) ]") | .command("main", "Build main files", { default: true }) | ||||||
| .action(async function main({ minify= "partial" }){ | .option("--no-types", "Also generate d.ts files", false) | ||||||
| 	for(const file_root of files){ | .action(function main({ types }){ | ||||||
| 		const file= file_root+".js"; | 	const regular = build({ | ||||||
| 		echo("Processing: "+ file); | 		files, | ||||||
| 		const out= filesOut(file); | 		filesOut, | ||||||
| 		const esbuild_output= s.$().run([ | 		minify: "no", | ||||||
| 			"npx esbuild '::file::'", | 		types, | ||||||
| 			"--platform=neutral", | 	}); | ||||||
| 			"--bundle", | 	const min = build({ | ||||||
| 			minify==="full" ? "--minify" : "--minify-syntax --minify-identifiers", | 		files, | ||||||
| 			"--legal-comments=inline", | 		filesOut(file, mark= "esm"){ | ||||||
| 			"--packages=external", | 			const out= filesOut(file, mark); | ||||||
| 			"--outfile='::out::'" | 			const idx= out.indexOf("."); | ||||||
| 		].join(" "), { file, out }); | 			return out.slice(0, idx)+".min"+out.slice(idx); | ||||||
| 		if(esbuild_output.code) | 		}, | ||||||
| 			return $.exit(esbuild_output.code, echo(esbuild_output.stderr)); | 		minify: "full", | ||||||
| 		echoVariant(esbuild_output.stderr.split("\n")[1].trim()+ " (esbuild)"); | 		types, | ||||||
| 		pipe( | 	}); | ||||||
| 			f=> f.replace(/^ +/gm, m=> "\t".repeat(m.length/2)), | 	return $.exit(regular + min); | ||||||
| 			f=> s.echo(f).to(out) | }) | ||||||
| 		)(s.cat(out)); | .command("signals", "Build only signals (for example for analysis)") | ||||||
|  | .action(function signals(){ | ||||||
| 		const file_dts= file_root+".d.ts"; | 	const regular = build({ | ||||||
| 		const file_dts_out= filesOut(file_dts); | 		files: [ "signals" ], | ||||||
| 		echoVariant(file_dts_out); | 		filesOut(file){ return "dist/."+file; }, | ||||||
| 		s.echo(bundleDTS(file_dts)).to(file_dts_out); | 		minify: "no", | ||||||
| 		 | 		iife: false, | ||||||
| 		await toDDE(out, file_root); | 	}); | ||||||
| 	} | 	return $.exit(regular); | ||||||
| 	$.exit(0); |  | ||||||
|  |  | ||||||
| 	async function toDDE(file, file_root){ |  | ||||||
| 		const name= "dde"; |  | ||||||
| 		const out= filesOut(file_root+".js", name); |  | ||||||
| 		echoVariant(`${out} (${file} → globalThis.${name})`) |  | ||||||
| 		 |  | ||||||
| 		let content= s.cat(file).toString().split(/export ?{/); |  | ||||||
| 		content.splice(1, 0, `\nglobalThis.${name}= {`); |  | ||||||
| 		content[2]= content[2].replace(/,(?!\n)/g, ",\n").replace(/(?<!\n)}/, "\n}").replace(/^(\t*)(.*) as ([^,\n]*)(,?)$/mg, "$1$3: $2$4"); |  | ||||||
| 		s.echo([ |  | ||||||
| 			`//deka-dom-el library is available via global namespace \`${name}\``, |  | ||||||
| 			"(()=> {", |  | ||||||
| 			content.join(""), |  | ||||||
| 			"})();" |  | ||||||
| 		].join("\n")).to(out); |  | ||||||
| 	} |  | ||||||
| }) | }) | ||||||
| .parse(); | .parse(); | ||||||
|  |  | ||||||
| function echoVariant(name){ |  | ||||||
| 	return echo("%c✓ "+name, css.info+css); | function filesOut(file, mark= "esm"){ return "dist/"+file.replace("index", mark); } | ||||||
| } |  | ||||||
|   | |||||||
							
								
								
									
										101
									
								
								bs/dev/.build.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										101
									
								
								bs/dev/.build.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,101 @@ | |||||||
|  | #!/usr/bin/env -S npx nodejsscript | ||||||
|  | import { buildSync as esbuildSync } from "esbuild"; | ||||||
|  | const css= echo.css` | ||||||
|  | 	.info{ color: gray; } | ||||||
|  | `; | ||||||
|  |  | ||||||
|  | export function build({ files, filesOut, minify= "partial", iife= true, types= true }){ | ||||||
|  | 	for(const file_root of files){ | ||||||
|  | 		const file= file_root+".js"; | ||||||
|  | 		echo(`Processing ${file} (minified: ${minify})`); | ||||||
|  | 		const out= filesOut(file); | ||||||
|  | 		esbuild({ file, out, minify }); | ||||||
|  |  | ||||||
|  | 		if(types){ | ||||||
|  | 			const file_dts= file_root+".d.ts"; | ||||||
|  | 			const file_dts_out= filesOut(file_dts); | ||||||
|  | 			echoVariant(file_dts_out, true); | ||||||
|  | 			buildDts({ | ||||||
|  | 				bundle: out, | ||||||
|  | 				entry: file_dts, | ||||||
|  | 			}); | ||||||
|  | 			echoVariant(file_dts_out); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		if(iife) toIIFE(file, file_root, types); | ||||||
|  | 	} | ||||||
|  | 	return 0; | ||||||
|  |  | ||||||
|  | 	function toIIFE(file, file_root, types){ | ||||||
|  | 		const fileMark= "iife"; | ||||||
|  | 		const name= "DDE"; | ||||||
|  | 		const out= filesOut(file_root+".js", fileMark); | ||||||
|  |  | ||||||
|  | 		const params= { | ||||||
|  | 			format: "iife", | ||||||
|  | 			globalName: name | ||||||
|  | 		}; | ||||||
|  | 		esbuild({ file, out, minify, params }); | ||||||
|  |  | ||||||
|  | 		if(!types) return; | ||||||
|  | 		const file_dts= file_root+".d.ts"; | ||||||
|  | 		const file_dts_out= filesOut(file_dts, fileMark); | ||||||
|  | 		echoVariant(file_dts_out, true); | ||||||
|  | 		buildDts({ | ||||||
|  | 			name: fileMark, | ||||||
|  | 			bundle: out, | ||||||
|  | 			entry: file_dts, | ||||||
|  | 		}) | ||||||
|  | 		echoVariant(file_dts_out); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | export function buildDts({ bundle, entry, name }){ | ||||||
|  | 	const out= bundle.slice(0, bundle.lastIndexOf("."))+".d.ts"; | ||||||
|  | 	const dts_b_g_output= s.run([ | ||||||
|  | 		"npx dts-bundle-generator", | ||||||
|  | 		"--silent", | ||||||
|  | 		"-o ::out::", | ||||||
|  | 		!name ? false : ("--umd-module-name "+name), | ||||||
|  | 		"--inline-declare-global", | ||||||
|  | 		"::entry::" | ||||||
|  | 	].filter(Boolean).join(" "), { out, entry }); | ||||||
|  | 	return dts_b_g_output; | ||||||
|  | } | ||||||
|  | export function esbuild({ file, out, minify= "partial", params= {} }){ | ||||||
|  | 	const esbuild_output= esbuildSync({ | ||||||
|  | 		entryPoints: [file], | ||||||
|  | 		outfile: out, | ||||||
|  | 		platform: "neutral", | ||||||
|  | 		bundle: true, | ||||||
|  | 		legalComments: "inline", | ||||||
|  | 		packages: "external", | ||||||
|  | 		metafile: true, | ||||||
|  | 		...minifyOption(minify), | ||||||
|  | 		...params | ||||||
|  | 	}); | ||||||
|  | 	pipe( | ||||||
|  | 		f=> f.replace(/^ +/gm, m=> "\t".repeat(m.length/2)), | ||||||
|  | 		f=> s.echo(f).to(out) | ||||||
|  | 	)(s.cat(out)); | ||||||
|  |  | ||||||
|  | 	echoVariant(metaToLineStatus(esbuild_output.metafile, out)); | ||||||
|  | 	return esbuild_output; | ||||||
|  | } | ||||||
|  | /** @param {"no"|"full"|"partial"} level */ | ||||||
|  | function minifyOption(level= "partial"){ | ||||||
|  | 	if("no"===level) return { minify: false }; | ||||||
|  | 	if("full"===level) return { minify: true }; | ||||||
|  | 	return { minifySyntax: true, minifyIdentifiers: true }; | ||||||
|  | } | ||||||
|  | function metaToLineStatus(meta, file){ | ||||||
|  | 	const status= meta.outputs[file]; | ||||||
|  | 	if(!status) return `? ${file}: unknown`; | ||||||
|  | 	const { bytes }= status; | ||||||
|  | 	const kbytes= bytes/1024; | ||||||
|  | 	const kbytesR= kbytes.toFixed(2); | ||||||
|  | 	return `${file}: ${kbytesR} kB`; | ||||||
|  | } | ||||||
|  | function echoVariant(name, todo= false){ | ||||||
|  | 	if(todo) return echo.use("-R", "~ "+name); | ||||||
|  | 	return echo("%c✓ "+name, css.info); | ||||||
|  | } | ||||||
							
								
								
									
										31
									
								
								bs/docs.js
									
									
									
									
									
								
							
							
						
						
									
										31
									
								
								bs/docs.js
									
									
									
									
									
								
							| @@ -1,14 +1,25 @@ | |||||||
| #!/usr/bin/env nodejsscript | #!/usr/bin/env -S npx nodejsscript | ||||||
| /* jshint esversion: 11,-W097, -W040, module: true, node: true, expr: true, undef: true *//* global echo, $, pipe, s, fetch, cyclicLoop */ | /* jshint esversion: 11,-W097, -W040, module: true, node: true, expr: true, undef: true *//* global echo, $, pipe, s, fetch, cyclicLoop */// editorconfig-checker-disable-line | ||||||
| echo("Building static documentation files…"); | echo("Building static documentation files…"); | ||||||
| echo("Preparing…"); | echo("Preparing…"); | ||||||
| import { path_target, pages as pages_registered, styles, dispatchEvent } from "../docs_src/ssr.js"; | import { path_target, pages as pages_registered, styles, dispatchEvent, t } from "../docs/ssr.js"; | ||||||
| import { createHTMl } from "./docs/jsdom.js"; | import { createHTMl } from "./docs/jsdom.js"; | ||||||
| import { register } from "../jsdom.js"; | import { register, queue } from "../jsdom.js"; | ||||||
| const pkg= s.cat("package.json").xargs(JSON.parse); | const pkg= s.cat("package.json").xargs(JSON.parse); | ||||||
|  |  | ||||||
|  | if(s.test("-d", path_target.root)){ | ||||||
|  | 	echo("Removing old files…"); | ||||||
|  | 	s.rm("-rf", path_target.root+"*"); | ||||||
|  | } else { | ||||||
|  | 	echo("Creating directory…"); | ||||||
|  | 	s.mkdir("-p", path_target.root); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Create assets directory in target | ||||||
|  | echo("Creating assets directory…"); | ||||||
|  | s.mkdir("-p", path_target.root+"assets"); | ||||||
| echo("Collecting list of pages…"); | echo("Collecting list of pages…"); | ||||||
| const pages= s.ls($.xdg.main`../docs_src/*.html.js`).map(addPage); | const pages= s.ls($.xdg.main`../docs/*.html.js`).map(addPage); | ||||||
| for(const { id, info } of pages){ | for(const { id, info } of pages){ | ||||||
| 	echo(`Generating ${id}.html…`); | 	echo(`Generating ${id}.html…`); | ||||||
| 	const serverDOM= createHTMl(""); | 	const serverDOM= createHTMl(""); | ||||||
| @@ -16,16 +27,24 @@ for(const { id, info } of pages){ | |||||||
| 		"HTMLScriptElement" | 		"HTMLScriptElement" | ||||||
| 	); | 	); | ||||||
| 	const { el }= await register(serverDOM.dom); | 	const { el }= await register(serverDOM.dom); | ||||||
| 	const { page }= await import(`../docs_src/${id}.html.js`); | 	const { page }= await import(`../docs/${id}.html.js`); | ||||||
| 	serverDOM.document.body.append( | 	serverDOM.document.body.append( | ||||||
| 		el(page, { pkg, info }), | 		el(page, { pkg, info }), | ||||||
| 	); | 	); | ||||||
|  | 	await queue(); | ||||||
|  |  | ||||||
| 	echo.use("-R", `Writing ${id}.html…`); | 	echo.use("-R", `Writing ${id}.html…`); | ||||||
| 	dispatchEvent("oneachrender", document); | 	dispatchEvent("oneachrender", document); | ||||||
| 	s.echo(serverDOM.serialize()).to(path_target.root+id+".html"); | 	s.echo(serverDOM.serialize()).to(path_target.root+id+".html"); | ||||||
| } | } | ||||||
| s.echo(styles.content).to(path_target.css+styles.name); | s.echo(styles.content).to(path_target.css+styles.name); | ||||||
|  |  | ||||||
|  | // Copy assets | ||||||
|  | echo("Copying assets…"); | ||||||
|  | if(s.test("-d", "docs/assets")) { | ||||||
|  | 	s.cp("-r", "docs/assets/*", path_target.assets); | ||||||
|  | } | ||||||
|  |  | ||||||
| dispatchEvent("onssrend"); | dispatchEvent("onssrend"); | ||||||
| echo("Done"); | echo("Done"); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,5 +1,5 @@ | |||||||
| import { JSDOM } from "jsdom"; | import { JSDOM } from "jsdom"; | ||||||
| const html_default= "<!doctype html><html><head><meta charset=\"utf-8\"></head><body></body></html>"; | const html_default= "<!doctype html><html lang=\"en\"><head><meta charset=\"utf-8\"></head><body></body></html>"; | ||||||
| let keys= []; | let keys= []; | ||||||
| let dom= null; | let dom= null; | ||||||
| import { relative } from 'node:path'; | import { relative } from 'node:path'; | ||||||
| @@ -10,7 +10,7 @@ export function createHTMl(html, options= {}){ | |||||||
| 	if(dom) cleanHTML(); | 	if(dom) cleanHTML(); | ||||||
| 	// set a default url if we don't get one - otherwise things explode when we copy localstorage keys | 	// set a default url if we don't get one - otherwise things explode when we copy localstorage keys | ||||||
| 	if (!('url' in options)) { Object.assign(options, { url: 'http://localhost:3000' }) } | 	if (!('url' in options)) { Object.assign(options, { url: 'http://localhost:3000' }) } | ||||||
| 	 |  | ||||||
| 	dom= new JSDOM(html, options); | 	dom= new JSDOM(html, options); | ||||||
| 	const window= dom.window; | 	const window= dom.window; | ||||||
| 	return { | 	return { | ||||||
|   | |||||||
							
								
								
									
										10
									
								
								bs/lint.sh
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								bs/lint.sh
									
									
									
									
									
								
							| @@ -1,3 +1,11 @@ | |||||||
| #!/usr/bin/env bash | #!/usr/bin/env bash | ||||||
|  | set -eou pipefail | ||||||
|  | # if $1=vim -no-color | ||||||
|  | one=${1:-''} | ||||||
|  | additional='' | ||||||
|  | [ "$one" = 'vim' ] && additional='-no-color' | ||||||
|  | npx editorconfig-checker -format gcc ${additional} | ||||||
|  | [ "$one" = 'vim' ] && additional='--reporter unix' | ||||||
|  | npx jshint index.js src ${additional} | ||||||
|  | [ "$one" = 'vim' ] && exit 0 | ||||||
| npx size-limit | npx size-limit | ||||||
| npx jshint index.js src |  | ||||||
|   | |||||||
							
								
								
									
										696
									
								
								dist/dde-with-signals.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										696
									
								
								dist/dde-with-signals.js
									
									
									
									
										vendored
									
									
								
							| @@ -1,696 +0,0 @@ | |||||||
| //deka-dom-el library is available via global namespace `dde` |  | ||||||
| (()=> { |  | ||||||
| // src/signals-common.js |  | ||||||
| var k = { |  | ||||||
| 	isSignal(t) { |  | ||||||
| 		return !1; |  | ||||||
| 	}, |  | ||||||
| 	processReactiveAttribute(t, e, n, r) { |  | ||||||
| 		return n; |  | ||||||
| 	} |  | ||||||
| }; |  | ||||||
| function B(t, e = !0) { |  | ||||||
| 	return e ? Object.assign(k, t) : (Object.setPrototypeOf(t, k), t); |  | ||||||
| } |  | ||||||
| function W(t) { |  | ||||||
| 	return k.isPrototypeOf(t) && t !== k ? t : k; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // src/helpers.js |  | ||||||
| var T = (...t) => Object.prototype.hasOwnProperty.call(...t); |  | ||||||
| function S(t) { |  | ||||||
| 	return typeof t > "u"; |  | ||||||
| } |  | ||||||
| function X(t) { |  | ||||||
| 	let e = typeof t; |  | ||||||
| 	return e !== "object" ? e : t === null ? "null" : Object.prototype.toString.call(t); |  | ||||||
| } |  | ||||||
| function q(t, e) { |  | ||||||
| 	if (!t || !(t instanceof AbortSignal)) |  | ||||||
| 		return !0; |  | ||||||
| 	if (!t.aborted) |  | ||||||
| 		return t.addEventListener("abort", e), function() { |  | ||||||
| 			t.removeEventListener("abort", e); |  | ||||||
| 		}; |  | ||||||
| } |  | ||||||
| function F(t, e) { |  | ||||||
| 	let { observedAttributes: n = [] } = t.constructor; |  | ||||||
| 	return n.reduce(function(r, o) { |  | ||||||
| 		return r[pt(o)] = e(t, o), r; |  | ||||||
| 	}, {}); |  | ||||||
| } |  | ||||||
| function pt(t) { |  | ||||||
| 	return t.replace(/-./g, (e) => e[1].toUpperCase()); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // src/dom-common.js |  | ||||||
| var d = { |  | ||||||
| 	setDeleteAttr: lt, |  | ||||||
| 	ssr: "", |  | ||||||
| 	D: globalThis.document, |  | ||||||
| 	F: globalThis.DocumentFragment, |  | ||||||
| 	H: globalThis.HTMLElement, |  | ||||||
| 	S: globalThis.SVGElement, |  | ||||||
| 	M: globalThis.MutationObserver |  | ||||||
| }; |  | ||||||
| function lt(t, e, n) { |  | ||||||
| 	if (Reflect.set(t, e, n), !!S(n)) { |  | ||||||
| 		if (Reflect.deleteProperty(t, e), t instanceof d.H && t.getAttribute(e) === "undefined") |  | ||||||
| 			return t.removeAttribute(e); |  | ||||||
| 		if (Reflect.get(t, e) === "undefined") |  | ||||||
| 			return Reflect.set(t, e, ""); |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| var C = "__dde_lifecyclesToEvents", _ = "dde:connected", O = "dde:disconnected", M = "dde:attributeChanged"; |  | ||||||
|  |  | ||||||
| // src/dom.js |  | ||||||
| var A = [{ |  | ||||||
| 	get scope() { |  | ||||||
| 		return d.D.body; |  | ||||||
| 	}, |  | ||||||
| 	host: (t) => t ? t(d.D.body) : d.D.body, |  | ||||||
| 	prevent: !0 |  | ||||||
| }], m = { |  | ||||||
| 	get current() { |  | ||||||
| 		return A[A.length - 1]; |  | ||||||
| 	}, |  | ||||||
| 	get host() { |  | ||||||
| 		return this.current.host; |  | ||||||
| 	}, |  | ||||||
| 	preventDefault() { |  | ||||||
| 		let { current: t } = this; |  | ||||||
| 		return t.prevent = !0, t; |  | ||||||
| 	}, |  | ||||||
| 	get state() { |  | ||||||
| 		return [...A]; |  | ||||||
| 	}, |  | ||||||
| 	push(t = {}) { |  | ||||||
| 		return A.push(Object.assign({}, this.current, { prevent: !1 }, t)); |  | ||||||
| 	}, |  | ||||||
| 	pushRoot() { |  | ||||||
| 		return A.push(A[0]); |  | ||||||
| 	}, |  | ||||||
| 	pop() { |  | ||||||
| 		if (A.length !== 1) |  | ||||||
| 			return A.pop(); |  | ||||||
| 	} |  | ||||||
| }; |  | ||||||
| function Y(...t) { |  | ||||||
| 	return this.appendOriginal(...t), this; |  | ||||||
| } |  | ||||||
| function ht(t) { |  | ||||||
| 	return t.append === Y || (t.appendOriginal = t.append, t.append = Y), t; |  | ||||||
| } |  | ||||||
| var $; |  | ||||||
| function j(t, e, ...n) { |  | ||||||
| 	let r = W(this), o = 0, c, i; |  | ||||||
| 	switch ((Object(e) !== e || r.isSignal(e)) && (e = { textContent: e }), !0) { |  | ||||||
| 		case typeof t == "function": { |  | ||||||
| 			o = 1, m.push({ scope: t, host: (...v) => v.length ? (o === 1 ? n.unshift(...v) : v.forEach((l) => l(i)), void 0) : i }), c = t(e || void 0); |  | ||||||
| 			let a = c instanceof d.F; |  | ||||||
| 			if (c.nodeName === "#comment") |  | ||||||
| 				break; |  | ||||||
| 			let h = j.mark({ |  | ||||||
| 				type: "component", |  | ||||||
| 				name: t.name, |  | ||||||
| 				host: a ? "this" : "parentElement" |  | ||||||
| 			}); |  | ||||||
| 			c.prepend(h), a && (i = h); |  | ||||||
| 			break; |  | ||||||
| 		} |  | ||||||
| 		case t === "#text": |  | ||||||
| 			c = P.call(this, d.D.createTextNode(""), e); |  | ||||||
| 			break; |  | ||||||
| 		case (t === "<>" || !t): |  | ||||||
| 			c = P.call(this, d.D.createDocumentFragment(), e); |  | ||||||
| 			break; |  | ||||||
| 		case !!$: |  | ||||||
| 			c = P.call(this, d.D.createElementNS($, t), e); |  | ||||||
| 			break; |  | ||||||
| 		case !c: |  | ||||||
| 			c = P.call(this, d.D.createElement(t), e); |  | ||||||
| 	} |  | ||||||
| 	return ht(c), i || (i = c), n.forEach((a) => a(i)), o && m.pop(), o = 2, c; |  | ||||||
| } |  | ||||||
| function Wt(t, e = t, n = void 0) { |  | ||||||
| 	let r = Symbol.for("default"), o = Array.from(e.querySelectorAll("slot")).reduce((i, a) => Reflect.set(i, a.name || r, a) && i, {}), c = T(o, r); |  | ||||||
| 	if (t.append = new Proxy(t.append, { |  | ||||||
| 		apply(i, a, h) { |  | ||||||
| 			if (!h.length) |  | ||||||
| 				return t; |  | ||||||
| 			let v = d.D.createDocumentFragment(); |  | ||||||
| 			for (let l of h) { |  | ||||||
| 				if (!l || !l.slot) { |  | ||||||
| 					c && v.appendChild(l); |  | ||||||
| 					continue; |  | ||||||
| 				} |  | ||||||
| 				let x = l.slot, y = o[x]; |  | ||||||
| 				vt(l, "remove", "slot"), y && (bt(y, l, n), Reflect.deleteProperty(o, x)); |  | ||||||
| 			} |  | ||||||
| 			return c && (o[r].replaceWith(v), Reflect.deleteProperty(o, r)), t.append = i, t; |  | ||||||
| 		} |  | ||||||
| 	}), t !== e) { |  | ||||||
| 		let i = Array.from(t.childNodes); |  | ||||||
| 		i.forEach((a) => a.remove()), t.append(...i); |  | ||||||
| 	} |  | ||||||
| 	return e; |  | ||||||
| } |  | ||||||
| function bt(t, e, n) { |  | ||||||
| 	n && n(t, e); |  | ||||||
| 	try { |  | ||||||
| 		t.replaceWith(P(e, { className: [e.className, t.className], dataset: { ...t.dataset } })); |  | ||||||
| 	} catch { |  | ||||||
| 		t.replaceWith(e); |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| j.mark = function(t, e = !1) { |  | ||||||
| 	t = Object.entries(t).map(([o, c]) => o + `="${c}"`).join(" "); |  | ||||||
| 	let n = e ? "" : "/", r = d.D.createComment(`<dde:mark ${t}${d.ssr}${n}>`); |  | ||||||
| 	return e && (r.end = d.D.createComment("</dde:mark>")), r; |  | ||||||
| }; |  | ||||||
| function qt(t) { |  | ||||||
| 	let e = this; |  | ||||||
| 	return function(...r) { |  | ||||||
| 		$ = t; |  | ||||||
| 		let o = j.call(e, ...r); |  | ||||||
| 		return $ = void 0, o; |  | ||||||
| 	}; |  | ||||||
| } |  | ||||||
| var U = /* @__PURE__ */ new WeakMap(), { setDeleteAttr: tt } = d; |  | ||||||
| function P(t, ...e) { |  | ||||||
| 	if (!e.length) |  | ||||||
| 		return t; |  | ||||||
| 	U.set(t, rt(t, this)); |  | ||||||
| 	for (let [n, r] of Object.entries(Object.assign({}, ...e))) |  | ||||||
| 		nt.call(this, t, n, r); |  | ||||||
| 	return U.delete(t), t; |  | ||||||
| } |  | ||||||
| function nt(t, e, n) { |  | ||||||
| 	let { setRemoveAttr: r, s: o } = rt(t, this), c = this; |  | ||||||
| 	n = o.processReactiveAttribute( |  | ||||||
| 		t, |  | ||||||
| 		e, |  | ||||||
| 		n, |  | ||||||
| 		(a, h) => nt.call(c, t, a, h) |  | ||||||
| 	); |  | ||||||
| 	let [i] = e; |  | ||||||
| 	if (i === "=") |  | ||||||
| 		return r(e.slice(1), n); |  | ||||||
| 	if (i === ".") |  | ||||||
| 		return et(t, e.slice(1), n); |  | ||||||
| 	if (/(aria|data)([A-Z])/.test(e)) |  | ||||||
| 		return e = e.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase(), r(e, n); |  | ||||||
| 	switch (e === "className" && (e = "class"), e) { |  | ||||||
| 		case "xlink:href": |  | ||||||
| 			return r(e, n, "http://www.w3.org/1999/xlink"); |  | ||||||
| 		case "textContent": |  | ||||||
| 			return tt(t, e, n); |  | ||||||
| 		case "style": |  | ||||||
| 			if (typeof n != "object") |  | ||||||
| 				break; |  | ||||||
| 		case "dataset": |  | ||||||
| 			return I(o, n, et.bind(null, t[e])); |  | ||||||
| 		case "ariaset": |  | ||||||
| 			return I(o, n, (a, h) => r("aria-" + a, h)); |  | ||||||
| 		case "classList": |  | ||||||
| 			return gt.call(c, t, n); |  | ||||||
| 	} |  | ||||||
| 	return Et(t, e) ? tt(t, e, n) : r(e, n); |  | ||||||
| } |  | ||||||
| function rt(t, e) { |  | ||||||
| 	if (U.has(t)) |  | ||||||
| 		return U.get(t); |  | ||||||
| 	let r = (t instanceof d.S ? xt : mt).bind(null, t, "Attribute"), o = W(e); |  | ||||||
| 	return { setRemoveAttr: r, s: o }; |  | ||||||
| } |  | ||||||
| function gt(t, e) { |  | ||||||
| 	let n = W(this); |  | ||||||
| 	return I( |  | ||||||
| 		n, |  | ||||||
| 		e, |  | ||||||
| 		(r, o) => t.classList.toggle(r, o === -1 ? void 0 : !!o) |  | ||||||
| 	), t; |  | ||||||
| } |  | ||||||
| function Ft(t) { |  | ||||||
| 	return Array.from(t.children).forEach((e) => e.remove()), t; |  | ||||||
| } |  | ||||||
| function vt(t, e, n, r) { |  | ||||||
| 	return t instanceof d.H ? t[e + "Attribute"](n, r) : t[e + "AttributeNS"](null, n, r); |  | ||||||
| } |  | ||||||
| function Et(t, e) { |  | ||||||
| 	if (!(e in t)) |  | ||||||
| 		return !1; |  | ||||||
| 	let n = ot(t, e); |  | ||||||
| 	return !S(n.set); |  | ||||||
| } |  | ||||||
| function ot(t, e) { |  | ||||||
| 	if (t = Object.getPrototypeOf(t), !t) |  | ||||||
| 		return {}; |  | ||||||
| 	let n = Object.getOwnPropertyDescriptor(t, e); |  | ||||||
| 	return n || ot(t, e); |  | ||||||
| } |  | ||||||
| function I(t, e, n) { |  | ||||||
| 	if (!(typeof e != "object" || e === null)) |  | ||||||
| 		return Object.entries(e).forEach(function([o, c]) { |  | ||||||
| 			o && (c = t.processReactiveAttribute(e, o, c, n), n(o, c)); |  | ||||||
| 		}); |  | ||||||
| } |  | ||||||
| function ct(t) { |  | ||||||
| 	return Array.isArray(t) ? t.filter(Boolean).join(" ") : t; |  | ||||||
| } |  | ||||||
| function mt(t, e, n, r) { |  | ||||||
| 	return t[(S(r) ? "remove" : "set") + e](n, ct(r)); |  | ||||||
| } |  | ||||||
| function xt(t, e, n, r, o = null) { |  | ||||||
| 	return t[(S(r) ? "remove" : "set") + e + "NS"](o, n, ct(r)); |  | ||||||
| } |  | ||||||
| function et(t, e, n) { |  | ||||||
| 	if (Reflect.set(t, e, n), !!S(n)) |  | ||||||
| 		return Reflect.deleteProperty(t, e); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // src/events-observer.js |  | ||||||
| var D = d.M ? wt() : new Proxy({}, { |  | ||||||
| 	get() { |  | ||||||
| 		return () => { |  | ||||||
| 		}; |  | ||||||
| 	} |  | ||||||
| }); |  | ||||||
| function wt() { |  | ||||||
| 	let t = /* @__PURE__ */ new Map(), e = !1, n = (s) => function(u) { |  | ||||||
| 		for (let f of u) |  | ||||||
| 			if (f.type === "childList") { |  | ||||||
| 				if (l(f.addedNodes, !0)) { |  | ||||||
| 					s(); |  | ||||||
| 					continue; |  | ||||||
| 				} |  | ||||||
| 				x(f.removedNodes, !0) && s(); |  | ||||||
| 			} |  | ||||||
| 	}, r = new d.M(n(a)); |  | ||||||
| 	return { |  | ||||||
| 		observe(s) { |  | ||||||
| 			let u = new d.M(n(() => { |  | ||||||
| 			})); |  | ||||||
| 			return u.observe(s, { childList: !0, subtree: !0 }), () => u.disconnect(); |  | ||||||
| 		}, |  | ||||||
| 		onConnected(s, u) { |  | ||||||
| 			i(); |  | ||||||
| 			let f = c(s); |  | ||||||
| 			f.connected.has(u) || (f.connected.add(u), f.length_c += 1); |  | ||||||
| 		}, |  | ||||||
| 		offConnected(s, u) { |  | ||||||
| 			if (!t.has(s)) |  | ||||||
| 				return; |  | ||||||
| 			let f = t.get(s); |  | ||||||
| 			f.connected.has(u) && (f.connected.delete(u), f.length_c -= 1, o(s, f)); |  | ||||||
| 		}, |  | ||||||
| 		onDisconnected(s, u) { |  | ||||||
| 			i(); |  | ||||||
| 			let f = c(s); |  | ||||||
| 			f.disconnected.has(u) || (f.disconnected.add(u), f.length_d += 1); |  | ||||||
| 		}, |  | ||||||
| 		offDisconnected(s, u) { |  | ||||||
| 			if (!t.has(s)) |  | ||||||
| 				return; |  | ||||||
| 			let f = t.get(s); |  | ||||||
| 			f.disconnected.has(u) && (f.disconnected.delete(u), f.length_d -= 1, o(s, f)); |  | ||||||
| 		} |  | ||||||
| 	}; |  | ||||||
| 	function o(s, u) { |  | ||||||
| 		u.length_c || u.length_d || (t.delete(s), a()); |  | ||||||
| 	} |  | ||||||
| 	function c(s) { |  | ||||||
| 		if (t.has(s)) |  | ||||||
| 			return t.get(s); |  | ||||||
| 		let u = { |  | ||||||
| 			connected: /* @__PURE__ */ new WeakSet(), |  | ||||||
| 			length_c: 0, |  | ||||||
| 			disconnected: /* @__PURE__ */ new WeakSet(), |  | ||||||
| 			length_d: 0 |  | ||||||
| 		}; |  | ||||||
| 		return t.set(s, u), u; |  | ||||||
| 	} |  | ||||||
| 	function i() { |  | ||||||
| 		e || (e = !0, r.observe(d.D.body, { childList: !0, subtree: !0 })); |  | ||||||
| 	} |  | ||||||
| 	function a() { |  | ||||||
| 		!e || t.size || (e = !1, r.disconnect()); |  | ||||||
| 	} |  | ||||||
| 	function h() { |  | ||||||
| 		return new Promise(function(s) { |  | ||||||
| 			(requestIdleCallback || requestAnimationFrame)(s); |  | ||||||
| 		}); |  | ||||||
| 	} |  | ||||||
| 	async function v(s) { |  | ||||||
| 		t.size > 30 && await h(); |  | ||||||
| 		let u = []; |  | ||||||
| 		if (!(s instanceof Node)) |  | ||||||
| 			return u; |  | ||||||
| 		for (let f of t.keys()) |  | ||||||
| 			f === s || !(f instanceof Node) || s.contains(f) && u.push(f); |  | ||||||
| 		return u; |  | ||||||
| 	} |  | ||||||
| 	function l(s, u) { |  | ||||||
| 		let f = !1; |  | ||||||
| 		for (let b of s) { |  | ||||||
| 			if (u && v(b).then(l), !t.has(b)) |  | ||||||
| 				continue; |  | ||||||
| 			let N = t.get(b); |  | ||||||
| 			N.length_c && (b.dispatchEvent(new Event(_)), N.connected = /* @__PURE__ */ new WeakSet(), N.length_c = 0, N.length_d || t.delete(b), f = !0); |  | ||||||
| 		} |  | ||||||
| 		return f; |  | ||||||
| 	} |  | ||||||
| 	function x(s, u) { |  | ||||||
| 		let f = !1; |  | ||||||
| 		for (let b of s) |  | ||||||
| 			u && v(b).then(x), !(!t.has(b) || !t.get(b).length_d) && ((globalThis.queueMicrotask || setTimeout)(y(b)), f = !0); |  | ||||||
| 		return f; |  | ||||||
| 	} |  | ||||||
| 	function y(s) { |  | ||||||
| 		return () => { |  | ||||||
| 			s.isConnected || (s.dispatchEvent(new Event(O)), t.delete(s)); |  | ||||||
| 		}; |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // src/customElement.js |  | ||||||
| function Zt(t, e, n, r = _t) { |  | ||||||
| 	m.push({ |  | ||||||
| 		scope: t, |  | ||||||
| 		host: (...i) => i.length ? i.forEach((a) => a(t)) : t |  | ||||||
| 	}), typeof r == "function" && (r = r.call(t, t)); |  | ||||||
| 	let o = t[C]; |  | ||||||
| 	o || yt(t); |  | ||||||
| 	let c = n.call(t, r); |  | ||||||
| 	return o || t.dispatchEvent(new Event(_)), e.nodeType === 11 && typeof e.mode == "string" && t.addEventListener(O, D.observe(e), { once: !0 }), m.pop(), e.append(c); |  | ||||||
| } |  | ||||||
| function yt(t) { |  | ||||||
| 	return J(t.prototype, "connectedCallback", function(e, n, r) { |  | ||||||
| 		e.apply(n, r), n.dispatchEvent(new Event(_)); |  | ||||||
| 	}), J(t.prototype, "disconnectedCallback", function(e, n, r) { |  | ||||||
| 		e.apply(n, r), (globalThis.queueMicrotask || setTimeout)( |  | ||||||
| 			() => !n.isConnected && n.dispatchEvent(new Event(O)) |  | ||||||
| 		); |  | ||||||
| 	}), J(t.prototype, "attributeChangedCallback", function(e, n, r) { |  | ||||||
| 		let [o, , c] = r; |  | ||||||
| 		n.dispatchEvent(new CustomEvent(M, { |  | ||||||
| 			detail: [o, c] |  | ||||||
| 		})), e.apply(n, r); |  | ||||||
| 	}), t.prototype[C] = !0, t; |  | ||||||
| } |  | ||||||
| function J(t, e, n) { |  | ||||||
| 	t[e] = new Proxy(t[e] || (() => { |  | ||||||
| 	}), { apply: n }); |  | ||||||
| } |  | ||||||
| function _t(t) { |  | ||||||
| 	return F(t, (e, n) => e.getAttribute(n)); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // src/events.js |  | ||||||
| function Qt(t, e, n) { |  | ||||||
| 	return e || (e = {}), function(o, ...c) { |  | ||||||
| 		n && (c.unshift(o), o = typeof n == "function" ? n() : n); |  | ||||||
| 		let i = c.length ? new CustomEvent(t, Object.assign({ detail: c[0] }, e)) : new Event(t, e); |  | ||||||
| 		return o.dispatchEvent(i); |  | ||||||
| 	}; |  | ||||||
| } |  | ||||||
| function w(t, e, n) { |  | ||||||
| 	return function(o) { |  | ||||||
| 		return o.addEventListener(t, e, n), o; |  | ||||||
| 	}; |  | ||||||
| } |  | ||||||
| var it = (t) => Object.assign({}, typeof t == "object" ? t : null, { once: !0 }); |  | ||||||
| w.connected = function(t, e) { |  | ||||||
| 	return e = it(e), function(r) { |  | ||||||
| 		return r.addEventListener(_, t, e), r[C] ? r : r.isConnected ? (r.dispatchEvent(new Event(_)), r) : (q(e.signal, () => D.offConnected(r, t)) && D.onConnected(r, t), r); |  | ||||||
| 	}; |  | ||||||
| }; |  | ||||||
| w.disconnected = function(t, e) { |  | ||||||
| 	return e = it(e), function(r) { |  | ||||||
| 		return r.addEventListener(O, t, e), r[C] || q(e.signal, () => D.offDisconnected(r, t)) && D.onDisconnected(r, t), r; |  | ||||||
| 	}; |  | ||||||
| }; |  | ||||||
| var Z = /* @__PURE__ */ new WeakMap(); |  | ||||||
| w.disconnectedAsAbort = function(t) { |  | ||||||
| 	if (Z.has(t)) |  | ||||||
| 		return Z.get(t); |  | ||||||
| 	let e = new AbortController(); |  | ||||||
| 	return Z.set(t, e), t(w.disconnected(() => e.abort())), e; |  | ||||||
| }; |  | ||||||
| var At = /* @__PURE__ */ new WeakSet(); |  | ||||||
| w.attributeChanged = function(t, e) { |  | ||||||
| 	return typeof e != "object" && (e = {}), function(r) { |  | ||||||
| 		if (r.addEventListener(M, t, e), r[C] || At.has(r) || !d.M) |  | ||||||
| 			return r; |  | ||||||
| 		let o = new d.M(function(i) { |  | ||||||
| 			for (let { attributeName: a, target: h } of i) |  | ||||||
| 				h.dispatchEvent( |  | ||||||
| 					new CustomEvent(M, { detail: [a, h.getAttribute(a)] }) |  | ||||||
| 				); |  | ||||||
| 		}); |  | ||||||
| 		return q(e.signal, () => o.disconnect()) && o.observe(r, { attributes: !0 }), r; |  | ||||||
| 	}; |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| // src/signals-lib.js |  | ||||||
| var p = "__dde_signal"; |  | ||||||
| function z(t) { |  | ||||||
| 	try { |  | ||||||
| 		return T(t, p); |  | ||||||
| 	} catch { |  | ||||||
| 		return !1; |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| var H = [], g = /* @__PURE__ */ new WeakMap(); |  | ||||||
| function E(t, e) { |  | ||||||
| 	if (typeof t != "function") |  | ||||||
| 		return st(!1, t, e); |  | ||||||
| 	if (z(t)) |  | ||||||
| 		return t; |  | ||||||
| 	let n = st(!0), r = function() { |  | ||||||
| 		let [o, ...c] = g.get(r); |  | ||||||
| 		if (g.set(r, /* @__PURE__ */ new Set([o])), H.push(r), dt(n, t()), H.pop(), !c.length) |  | ||||||
| 			return; |  | ||||||
| 		let i = g.get(r); |  | ||||||
| 		for (let a of c) |  | ||||||
| 			i.has(a) || L(a, r); |  | ||||||
| 	}; |  | ||||||
| 	return g.set(n[p], r), g.set(r, /* @__PURE__ */ new Set([n])), r(), n; |  | ||||||
| } |  | ||||||
| E.action = function(t, e, ...n) { |  | ||||||
| 	let r = t[p], { actions: o } = r; |  | ||||||
| 	if (!o || !(e in o)) |  | ||||||
| 		throw new Error(`'${t}' has no action with name '${e}'!`); |  | ||||||
| 	if (o[e].apply(r, n), r.skip) |  | ||||||
| 		return delete r.skip; |  | ||||||
| 	r.listeners.forEach((c) => c(r.value)); |  | ||||||
| }; |  | ||||||
| E.on = function t(e, n, r = {}) { |  | ||||||
| 	let { signal: o } = r; |  | ||||||
| 	if (!(o && o.aborted)) { |  | ||||||
| 		if (Array.isArray(e)) |  | ||||||
| 			return e.forEach((c) => t(c, n, r)); |  | ||||||
| 		Q(e, n), o && o.addEventListener("abort", () => L(e, n)); |  | ||||||
| 	} |  | ||||||
| }; |  | ||||||
| E.symbols = { |  | ||||||
| 	//signal: mark, |  | ||||||
| 	onclear: Symbol.for("Signal.onclear") |  | ||||||
| }; |  | ||||||
| E.clear = function(...t) { |  | ||||||
| 	for (let n of t) { |  | ||||||
| 		let r = n[p]; |  | ||||||
| 		r && (delete n.toJSON, r.onclear.forEach((o) => o.call(r)), e(n, r), delete n[p]); |  | ||||||
| 	} |  | ||||||
| 	function e(n, r) { |  | ||||||
| 		r.listeners.forEach((o) => { |  | ||||||
| 			if (r.listeners.delete(o), !g.has(o)) |  | ||||||
| 				return; |  | ||||||
| 			let c = g.get(o); |  | ||||||
| 			c.delete(n), !(c.size > 1) && (n.clear(...c), g.delete(o)); |  | ||||||
| 		}); |  | ||||||
| 	} |  | ||||||
| }; |  | ||||||
| var R = "__dde_reactive"; |  | ||||||
| E.el = function(t, e) { |  | ||||||
| 	let n = j.mark({ type: "reactive" }, !0), r = n.end, o = d.D.createDocumentFragment(); |  | ||||||
| 	o.append(n, r); |  | ||||||
| 	let { current: c } = m, i = {}, a = (h) => { |  | ||||||
| 		if (!n.parentNode || !r.parentNode) |  | ||||||
| 			return L(t, a); |  | ||||||
| 		let v = i; |  | ||||||
| 		i = {}, m.push(c); |  | ||||||
| 		let l = e(h, function(u, f) { |  | ||||||
| 			let b; |  | ||||||
| 			return T(v, u) ? (b = v[u], delete v[u]) : b = f(), i[u] = b, b; |  | ||||||
| 		}); |  | ||||||
| 		m.pop(), Array.isArray(l) || (l = [l]); |  | ||||||
| 		let x = document.createComment(""); |  | ||||||
| 		l.push(x), n.after(...l); |  | ||||||
| 		let y; |  | ||||||
| 		for (; (y = x.nextSibling) && y !== r; ) |  | ||||||
| 			y.remove(); |  | ||||||
| 		x.remove(), n.isConnected && St(c.host()); |  | ||||||
| 	}; |  | ||||||
| 	return Q(t, a), ft(t, a, n, e), a(t()), o; |  | ||||||
| }; |  | ||||||
| function St(t) { |  | ||||||
| 	!t || !t[R] || (requestIdleCallback || setTimeout)(function() { |  | ||||||
| 		t[R] = t[R].filter(([e, n]) => n.isConnected ? !0 : (L(...e), !1)); |  | ||||||
| 	}); |  | ||||||
| } |  | ||||||
| var Ct = { |  | ||||||
| 	_set(t) { |  | ||||||
| 		this.value = t; |  | ||||||
| 	} |  | ||||||
| }; |  | ||||||
| function Ot(t) { |  | ||||||
| 	return function(e, n) { |  | ||||||
| 		let r = (...c) => c.length ? e.setAttribute(n, ...c) : K(r), o = at(r, e.getAttribute(n), Ct); |  | ||||||
| 		return t[n] = o, o; |  | ||||||
| 	}; |  | ||||||
| } |  | ||||||
| var G = "__dde_attributes"; |  | ||||||
| E.observedAttributes = function(t) { |  | ||||||
| 	let e = t[G] = {}, n = F(t, Ot(e)); |  | ||||||
| 	return w.attributeChanged(function({ detail: o }) { |  | ||||||
| 		/*! This maps attributes to signals (`S.observedAttributes`). |  | ||||||
| 			* Investigate `__dde_attributes` key of the element.*/ |  | ||||||
| 		let [c, i] = o, a = this[G][c]; |  | ||||||
| 		if (a) |  | ||||||
| 			return E.action(a, "_set", i); |  | ||||||
| 	})(t), w.disconnected(function() { |  | ||||||
| 		/*! This removes all signals mapped to attributes (`S.observedAttributes`). |  | ||||||
| 			* Investigate `__dde_attributes` key of the element.*/ |  | ||||||
| 		E.clear(...Object.values(this[G])); |  | ||||||
| 	})(t), n; |  | ||||||
| }; |  | ||||||
| var ut = { |  | ||||||
| 	isSignal: z, |  | ||||||
| 	processReactiveAttribute(t, e, n, r) { |  | ||||||
| 		if (!z(n)) |  | ||||||
| 			return n; |  | ||||||
| 		let o = (c) => { |  | ||||||
| 			if (!t.isConnected) |  | ||||||
| 				return L(n, o); |  | ||||||
| 			r(e, c); |  | ||||||
| 		}; |  | ||||||
| 		return Q(n, o), ft(n, o, t, e), n(); |  | ||||||
| 	} |  | ||||||
| }; |  | ||||||
| function ft(t, e, ...n) { |  | ||||||
| 	let { current: r } = m; |  | ||||||
| 	r.prevent || r.host(function(o) { |  | ||||||
| 		o[R] || (o[R] = [], w.disconnected( |  | ||||||
| 			() => ( |  | ||||||
| 				/*! |  | ||||||
| 				* Clears all Signals listeners added in the current scope/host (`S.el`, `assign`, …?). |  | ||||||
| 				* You can investigate the `__dde_reactive` key of the element. |  | ||||||
| 				* */ |  | ||||||
| 				o[R].forEach(([[c, i]]) => L(c, i, c[p] && c[p].host && c[p].host() === o)) |  | ||||||
| 			) |  | ||||||
| 		)(o)), o[R].push([[t, e], ...n]); |  | ||||||
| 	}); |  | ||||||
| } |  | ||||||
| function st(t, e, n) { |  | ||||||
| 	let r = t ? () => K(r) : (...o) => o.length ? dt(r, ...o) : K(r); |  | ||||||
| 	return at(r, e, n, t); |  | ||||||
| } |  | ||||||
| var Dt = Object.assign(/* @__PURE__ */ Object.create(null), { |  | ||||||
| 	stopPropagation() { |  | ||||||
| 		this.skip = !0; |  | ||||||
| 	} |  | ||||||
| }), V = class extends Error { |  | ||||||
| 	constructor() { |  | ||||||
| 		super(); |  | ||||||
| 		let [e, ...n] = this.stack.split(` |  | ||||||
| `), r = e.slice(e.indexOf("@"), e.indexOf(".js:") + 4); |  | ||||||
| 		this.stack = n.find((o) => !o.includes(r)); |  | ||||||
| 	} |  | ||||||
| }; |  | ||||||
| function at(t, e, n, r = !1) { |  | ||||||
| 	let o = []; |  | ||||||
| 	X(n) !== "[object Object]" && (n = {}); |  | ||||||
| 	let { onclear: c } = E.symbols; |  | ||||||
| 	n[c] && (o.push(n[c]), delete n[c]); |  | ||||||
| 	let { host: i } = m; |  | ||||||
| 	return Reflect.defineProperty(t, p, { |  | ||||||
| 		value: { |  | ||||||
| 			value: e, |  | ||||||
| 			actions: n, |  | ||||||
| 			onclear: o, |  | ||||||
| 			host: i, |  | ||||||
| 			listeners: /* @__PURE__ */ new Set(), |  | ||||||
| 			defined: new V().stack, |  | ||||||
| 			readonly: r |  | ||||||
| 		}, |  | ||||||
| 		enumerable: !1, |  | ||||||
| 		writable: !1, |  | ||||||
| 		configurable: !0 |  | ||||||
| 	}), t.toJSON = () => t(), t.valueOf = () => t[p] && t[p].value, Object.setPrototypeOf(t[p], Dt), t; |  | ||||||
| } |  | ||||||
| function Rt() { |  | ||||||
| 	return H[H.length - 1]; |  | ||||||
| } |  | ||||||
| function K(t) { |  | ||||||
| 	if (!t[p]) |  | ||||||
| 		return; |  | ||||||
| 	let { value: e, listeners: n } = t[p], r = Rt(); |  | ||||||
| 	return r && n.add(r), g.has(r) && g.get(r).add(t), e; |  | ||||||
| } |  | ||||||
| function dt(t, e, n) { |  | ||||||
| 	if (!t[p]) |  | ||||||
| 		return; |  | ||||||
| 	let r = t[p]; |  | ||||||
| 	if (!(!n && r.value === e)) |  | ||||||
| 		return r.value = e, r.listeners.forEach((o) => o(e)), e; |  | ||||||
| } |  | ||||||
| function Q(t, e) { |  | ||||||
| 	if (t[p]) |  | ||||||
| 		return t[p].listeners.add(e); |  | ||||||
| } |  | ||||||
| function L(t, e, n) { |  | ||||||
| 	let r = t[p]; |  | ||||||
| 	if (!r) |  | ||||||
| 		return; |  | ||||||
| 	let o = r.listeners.delete(e); |  | ||||||
| 	if (n && !r.listeners.size) { |  | ||||||
| 		if (E.clear(t), !g.has(r)) |  | ||||||
| 			return o; |  | ||||||
| 		let c = g.get(r); |  | ||||||
| 		if (!g.has(c)) |  | ||||||
| 			return o; |  | ||||||
| 		g.get(c).forEach((i) => L(i, c, !0)); |  | ||||||
| 	} |  | ||||||
| 	return o; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // signals.js |  | ||||||
| B(ut); |  | ||||||
|  |  | ||||||
| globalThis.dde= { |  | ||||||
| 	S: E, |  | ||||||
| 	assign: P, |  | ||||||
| 	assignAttribute: nt, |  | ||||||
| 	chainableAppend: ht, |  | ||||||
| 	classListDeclarative: gt, |  | ||||||
| 	createElement: j, |  | ||||||
| 	createElementNS: qt, |  | ||||||
| 	customElementRender: Zt, |  | ||||||
| 	customElementWithDDE: yt, |  | ||||||
| 	dispatchEvent: Qt, |  | ||||||
| 	el: j, |  | ||||||
| 	elNS: qt, |  | ||||||
| 	elementAttribute: vt, |  | ||||||
| 	empty: Ft, |  | ||||||
| 	isSignal: z, |  | ||||||
| 	lifecyclesToEvents: yt, |  | ||||||
| 	observedAttributes: _t, |  | ||||||
| 	on: w, |  | ||||||
| 	registerReactivity: B, |  | ||||||
| 	scope: m, |  | ||||||
| 	signal: E, |  | ||||||
| 	simulateSlots: Wt |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| })(); |  | ||||||
							
								
								
									
										473
									
								
								dist/dde.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										473
									
								
								dist/dde.js
									
									
									
									
										vendored
									
									
								
							| @@ -1,473 +0,0 @@ | |||||||
| //deka-dom-el library is available via global namespace `dde` |  | ||||||
| (()=> { |  | ||||||
| // src/signals-common.js |  | ||||||
| var C = { |  | ||||||
| 	isSignal(t) { |  | ||||||
| 		return !1; |  | ||||||
| 	}, |  | ||||||
| 	processReactiveAttribute(t, e, n, r) { |  | ||||||
| 		return n; |  | ||||||
| 	} |  | ||||||
| }; |  | ||||||
| function V(t, e = !0) { |  | ||||||
| 	return e ? Object.assign(C, t) : (Object.setPrototypeOf(t, C), t); |  | ||||||
| } |  | ||||||
| function L(t) { |  | ||||||
| 	return C.isPrototypeOf(t) && t !== C ? t : C; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // src/helpers.js |  | ||||||
| var q = (...t) => Object.prototype.hasOwnProperty.call(...t); |  | ||||||
| function E(t) { |  | ||||||
| 	return typeof t > "u"; |  | ||||||
| } |  | ||||||
| function N(t, e) { |  | ||||||
| 	if (!t || !(t instanceof AbortSignal)) |  | ||||||
| 		return !0; |  | ||||||
| 	if (!t.aborted) |  | ||||||
| 		return t.addEventListener("abort", e), function() { |  | ||||||
| 			t.removeEventListener("abort", e); |  | ||||||
| 		}; |  | ||||||
| } |  | ||||||
| function F(t, e) { |  | ||||||
| 	let { observedAttributes: n = [] } = t.constructor; |  | ||||||
| 	return n.reduce(function(r, o) { |  | ||||||
| 		return r[J(o)] = e(t, o), r; |  | ||||||
| 	}, {}); |  | ||||||
| } |  | ||||||
| function J(t) { |  | ||||||
| 	return t.replace(/-./g, (e) => e[1].toUpperCase()); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // src/dom-common.js |  | ||||||
| var a = { |  | ||||||
| 	setDeleteAttr: K, |  | ||||||
| 	ssr: "", |  | ||||||
| 	D: globalThis.document, |  | ||||||
| 	F: globalThis.DocumentFragment, |  | ||||||
| 	H: globalThis.HTMLElement, |  | ||||||
| 	S: globalThis.SVGElement, |  | ||||||
| 	M: globalThis.MutationObserver |  | ||||||
| }; |  | ||||||
| function K(t, e, n) { |  | ||||||
| 	if (Reflect.set(t, e, n), !!E(n)) { |  | ||||||
| 		if (Reflect.deleteProperty(t, e), t instanceof a.H && t.getAttribute(e) === "undefined") |  | ||||||
| 			return t.removeAttribute(e); |  | ||||||
| 		if (Reflect.get(t, e) === "undefined") |  | ||||||
| 			return Reflect.set(t, e, ""); |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| var x = "__dde_lifecyclesToEvents", g = "dde:connected", y = "dde:disconnected", D = "dde:attributeChanged"; |  | ||||||
|  |  | ||||||
| // src/dom.js |  | ||||||
| var v = [{ |  | ||||||
| 	get scope() { |  | ||||||
| 		return a.D.body; |  | ||||||
| 	}, |  | ||||||
| 	host: (t) => t ? t(a.D.body) : a.D.body, |  | ||||||
| 	prevent: !0 |  | ||||||
| }], S = { |  | ||||||
| 	get current() { |  | ||||||
| 		return v[v.length - 1]; |  | ||||||
| 	}, |  | ||||||
| 	get host() { |  | ||||||
| 		return this.current.host; |  | ||||||
| 	}, |  | ||||||
| 	preventDefault() { |  | ||||||
| 		let { current: t } = this; |  | ||||||
| 		return t.prevent = !0, t; |  | ||||||
| 	}, |  | ||||||
| 	get state() { |  | ||||||
| 		return [...v]; |  | ||||||
| 	}, |  | ||||||
| 	push(t = {}) { |  | ||||||
| 		return v.push(Object.assign({}, this.current, { prevent: !1 }, t)); |  | ||||||
| 	}, |  | ||||||
| 	pushRoot() { |  | ||||||
| 		return v.push(v[0]); |  | ||||||
| 	}, |  | ||||||
| 	pop() { |  | ||||||
| 		if (v.length !== 1) |  | ||||||
| 			return v.pop(); |  | ||||||
| 	} |  | ||||||
| }; |  | ||||||
| function $(...t) { |  | ||||||
| 	return this.appendOriginal(...t), this; |  | ||||||
| } |  | ||||||
| function Q(t) { |  | ||||||
| 	return t.append === $ || (t.appendOriginal = t.append, t.append = $), t; |  | ||||||
| } |  | ||||||
| var T; |  | ||||||
| function k(t, e, ...n) { |  | ||||||
| 	let r = L(this), o = 0, c, f; |  | ||||||
| 	switch ((Object(e) !== e || r.isSignal(e)) && (e = { textContent: e }), !0) { |  | ||||||
| 		case typeof t == "function": { |  | ||||||
| 			o = 1, S.push({ scope: t, host: (...b) => b.length ? (o === 1 ? n.unshift(...b) : b.forEach((l) => l(f)), void 0) : f }), c = t(e || void 0); |  | ||||||
| 			let d = c instanceof a.F; |  | ||||||
| 			if (c.nodeName === "#comment") |  | ||||||
| 				break; |  | ||||||
| 			let p = k.mark({ |  | ||||||
| 				type: "component", |  | ||||||
| 				name: t.name, |  | ||||||
| 				host: d ? "this" : "parentElement" |  | ||||||
| 			}); |  | ||||||
| 			c.prepend(p), d && (f = p); |  | ||||||
| 			break; |  | ||||||
| 		} |  | ||||||
| 		case t === "#text": |  | ||||||
| 			c = O.call(this, a.D.createTextNode(""), e); |  | ||||||
| 			break; |  | ||||||
| 		case (t === "<>" || !t): |  | ||||||
| 			c = O.call(this, a.D.createDocumentFragment(), e); |  | ||||||
| 			break; |  | ||||||
| 		case !!T: |  | ||||||
| 			c = O.call(this, a.D.createElementNS(T, t), e); |  | ||||||
| 			break; |  | ||||||
| 		case !c: |  | ||||||
| 			c = O.call(this, a.D.createElement(t), e); |  | ||||||
| 	} |  | ||||||
| 	return Q(c), f || (f = c), n.forEach((d) => d(f)), o && S.pop(), o = 2, c; |  | ||||||
| } |  | ||||||
| function bt(t, e = t, n = void 0) { |  | ||||||
| 	let r = Symbol.for("default"), o = Array.from(e.querySelectorAll("slot")).reduce((f, d) => Reflect.set(f, d.name || r, d) && f, {}), c = q(o, r); |  | ||||||
| 	if (t.append = new Proxy(t.append, { |  | ||||||
| 		apply(f, d, p) { |  | ||||||
| 			if (!p.length) |  | ||||||
| 				return t; |  | ||||||
| 			let b = a.D.createDocumentFragment(); |  | ||||||
| 			for (let l of p) { |  | ||||||
| 				if (!l || !l.slot) { |  | ||||||
| 					c && b.appendChild(l); |  | ||||||
| 					continue; |  | ||||||
| 				} |  | ||||||
| 				let A = l.slot, _ = o[A]; |  | ||||||
| 				tt(l, "remove", "slot"), _ && (X(_, l, n), Reflect.deleteProperty(o, A)); |  | ||||||
| 			} |  | ||||||
| 			return c && (o[r].replaceWith(b), Reflect.deleteProperty(o, r)), t.append = f, t; |  | ||||||
| 		} |  | ||||||
| 	}), t !== e) { |  | ||||||
| 		let f = Array.from(t.childNodes); |  | ||||||
| 		f.forEach((d) => d.remove()), t.append(...f); |  | ||||||
| 	} |  | ||||||
| 	return e; |  | ||||||
| } |  | ||||||
| function X(t, e, n) { |  | ||||||
| 	n && n(t, e); |  | ||||||
| 	try { |  | ||||||
| 		t.replaceWith(O(e, { className: [e.className, t.className], dataset: { ...t.dataset } })); |  | ||||||
| 	} catch { |  | ||||||
| 		t.replaceWith(e); |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| k.mark = function(t, e = !1) { |  | ||||||
| 	t = Object.entries(t).map(([o, c]) => o + `="${c}"`).join(" "); |  | ||||||
| 	let n = e ? "" : "/", r = a.D.createComment(`<dde:mark ${t}${a.ssr}${n}>`); |  | ||||||
| 	return e && (r.end = a.D.createComment("</dde:mark>")), r; |  | ||||||
| }; |  | ||||||
| function gt(t) { |  | ||||||
| 	let e = this; |  | ||||||
| 	return function(...r) { |  | ||||||
| 		T = t; |  | ||||||
| 		let o = k.call(e, ...r); |  | ||||||
| 		return T = void 0, o; |  | ||||||
| 	}; |  | ||||||
| } |  | ||||||
| var P = /* @__PURE__ */ new WeakMap(), { setDeleteAttr: U } = a; |  | ||||||
| function O(t, ...e) { |  | ||||||
| 	if (!e.length) |  | ||||||
| 		return t; |  | ||||||
| 	P.set(t, B(t, this)); |  | ||||||
| 	for (let [n, r] of Object.entries(Object.assign({}, ...e))) |  | ||||||
| 		z.call(this, t, n, r); |  | ||||||
| 	return P.delete(t), t; |  | ||||||
| } |  | ||||||
| function z(t, e, n) { |  | ||||||
| 	let { setRemoveAttr: r, s: o } = B(t, this), c = this; |  | ||||||
| 	n = o.processReactiveAttribute( |  | ||||||
| 		t, |  | ||||||
| 		e, |  | ||||||
| 		n, |  | ||||||
| 		(d, p) => z.call(c, t, d, p) |  | ||||||
| 	); |  | ||||||
| 	let [f] = e; |  | ||||||
| 	if (f === "=") |  | ||||||
| 		return r(e.slice(1), n); |  | ||||||
| 	if (f === ".") |  | ||||||
| 		return H(t, e.slice(1), n); |  | ||||||
| 	if (/(aria|data)([A-Z])/.test(e)) |  | ||||||
| 		return e = e.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase(), r(e, n); |  | ||||||
| 	switch (e === "className" && (e = "class"), e) { |  | ||||||
| 		case "xlink:href": |  | ||||||
| 			return r(e, n, "http://www.w3.org/1999/xlink"); |  | ||||||
| 		case "textContent": |  | ||||||
| 			return U(t, e, n); |  | ||||||
| 		case "style": |  | ||||||
| 			if (typeof n != "object") |  | ||||||
| 				break; |  | ||||||
| 		case "dataset": |  | ||||||
| 			return M(o, n, H.bind(null, t[e])); |  | ||||||
| 		case "ariaset": |  | ||||||
| 			return M(o, n, (d, p) => r("aria-" + d, p)); |  | ||||||
| 		case "classList": |  | ||||||
| 			return Y.call(c, t, n); |  | ||||||
| 	} |  | ||||||
| 	return et(t, e) ? U(t, e, n) : r(e, n); |  | ||||||
| } |  | ||||||
| function B(t, e) { |  | ||||||
| 	if (P.has(t)) |  | ||||||
| 		return P.get(t); |  | ||||||
| 	let r = (t instanceof a.S ? rt : nt).bind(null, t, "Attribute"), o = L(e); |  | ||||||
| 	return { setRemoveAttr: r, s: o }; |  | ||||||
| } |  | ||||||
| function Y(t, e) { |  | ||||||
| 	let n = L(this); |  | ||||||
| 	return M( |  | ||||||
| 		n, |  | ||||||
| 		e, |  | ||||||
| 		(r, o) => t.classList.toggle(r, o === -1 ? void 0 : !!o) |  | ||||||
| 	), t; |  | ||||||
| } |  | ||||||
| function vt(t) { |  | ||||||
| 	return Array.from(t.children).forEach((e) => e.remove()), t; |  | ||||||
| } |  | ||||||
| function tt(t, e, n, r) { |  | ||||||
| 	return t instanceof a.H ? t[e + "Attribute"](n, r) : t[e + "AttributeNS"](null, n, r); |  | ||||||
| } |  | ||||||
| function et(t, e) { |  | ||||||
| 	if (!(e in t)) |  | ||||||
| 		return !1; |  | ||||||
| 	let n = I(t, e); |  | ||||||
| 	return !E(n.set); |  | ||||||
| } |  | ||||||
| function I(t, e) { |  | ||||||
| 	if (t = Object.getPrototypeOf(t), !t) |  | ||||||
| 		return {}; |  | ||||||
| 	let n = Object.getOwnPropertyDescriptor(t, e); |  | ||||||
| 	return n || I(t, e); |  | ||||||
| } |  | ||||||
| function M(t, e, n) { |  | ||||||
| 	if (!(typeof e != "object" || e === null)) |  | ||||||
| 		return Object.entries(e).forEach(function([o, c]) { |  | ||||||
| 			o && (c = t.processReactiveAttribute(e, o, c, n), n(o, c)); |  | ||||||
| 		}); |  | ||||||
| } |  | ||||||
| function Z(t) { |  | ||||||
| 	return Array.isArray(t) ? t.filter(Boolean).join(" ") : t; |  | ||||||
| } |  | ||||||
| function nt(t, e, n, r) { |  | ||||||
| 	return t[(E(r) ? "remove" : "set") + e](n, Z(r)); |  | ||||||
| } |  | ||||||
| function rt(t, e, n, r, o = null) { |  | ||||||
| 	return t[(E(r) ? "remove" : "set") + e + "NS"](o, n, Z(r)); |  | ||||||
| } |  | ||||||
| function H(t, e, n) { |  | ||||||
| 	if (Reflect.set(t, e, n), !!E(n)) |  | ||||||
| 		return Reflect.deleteProperty(t, e); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // src/events-observer.js |  | ||||||
| var w = a.M ? ot() : new Proxy({}, { |  | ||||||
| 	get() { |  | ||||||
| 		return () => { |  | ||||||
| 		}; |  | ||||||
| 	} |  | ||||||
| }); |  | ||||||
| function ot() { |  | ||||||
| 	let t = /* @__PURE__ */ new Map(), e = !1, n = (i) => function(u) { |  | ||||||
| 		for (let s of u) |  | ||||||
| 			if (s.type === "childList") { |  | ||||||
| 				if (l(s.addedNodes, !0)) { |  | ||||||
| 					i(); |  | ||||||
| 					continue; |  | ||||||
| 				} |  | ||||||
| 				A(s.removedNodes, !0) && i(); |  | ||||||
| 			} |  | ||||||
| 	}, r = new a.M(n(d)); |  | ||||||
| 	return { |  | ||||||
| 		observe(i) { |  | ||||||
| 			let u = new a.M(n(() => { |  | ||||||
| 			})); |  | ||||||
| 			return u.observe(i, { childList: !0, subtree: !0 }), () => u.disconnect(); |  | ||||||
| 		}, |  | ||||||
| 		onConnected(i, u) { |  | ||||||
| 			f(); |  | ||||||
| 			let s = c(i); |  | ||||||
| 			s.connected.has(u) || (s.connected.add(u), s.length_c += 1); |  | ||||||
| 		}, |  | ||||||
| 		offConnected(i, u) { |  | ||||||
| 			if (!t.has(i)) |  | ||||||
| 				return; |  | ||||||
| 			let s = t.get(i); |  | ||||||
| 			s.connected.has(u) && (s.connected.delete(u), s.length_c -= 1, o(i, s)); |  | ||||||
| 		}, |  | ||||||
| 		onDisconnected(i, u) { |  | ||||||
| 			f(); |  | ||||||
| 			let s = c(i); |  | ||||||
| 			s.disconnected.has(u) || (s.disconnected.add(u), s.length_d += 1); |  | ||||||
| 		}, |  | ||||||
| 		offDisconnected(i, u) { |  | ||||||
| 			if (!t.has(i)) |  | ||||||
| 				return; |  | ||||||
| 			let s = t.get(i); |  | ||||||
| 			s.disconnected.has(u) && (s.disconnected.delete(u), s.length_d -= 1, o(i, s)); |  | ||||||
| 		} |  | ||||||
| 	}; |  | ||||||
| 	function o(i, u) { |  | ||||||
| 		u.length_c || u.length_d || (t.delete(i), d()); |  | ||||||
| 	} |  | ||||||
| 	function c(i) { |  | ||||||
| 		if (t.has(i)) |  | ||||||
| 			return t.get(i); |  | ||||||
| 		let u = { |  | ||||||
| 			connected: /* @__PURE__ */ new WeakSet(), |  | ||||||
| 			length_c: 0, |  | ||||||
| 			disconnected: /* @__PURE__ */ new WeakSet(), |  | ||||||
| 			length_d: 0 |  | ||||||
| 		}; |  | ||||||
| 		return t.set(i, u), u; |  | ||||||
| 	} |  | ||||||
| 	function f() { |  | ||||||
| 		e || (e = !0, r.observe(a.D.body, { childList: !0, subtree: !0 })); |  | ||||||
| 	} |  | ||||||
| 	function d() { |  | ||||||
| 		!e || t.size || (e = !1, r.disconnect()); |  | ||||||
| 	} |  | ||||||
| 	function p() { |  | ||||||
| 		return new Promise(function(i) { |  | ||||||
| 			(requestIdleCallback || requestAnimationFrame)(i); |  | ||||||
| 		}); |  | ||||||
| 	} |  | ||||||
| 	async function b(i) { |  | ||||||
| 		t.size > 30 && await p(); |  | ||||||
| 		let u = []; |  | ||||||
| 		if (!(i instanceof Node)) |  | ||||||
| 			return u; |  | ||||||
| 		for (let s of t.keys()) |  | ||||||
| 			s === i || !(s instanceof Node) || i.contains(s) && u.push(s); |  | ||||||
| 		return u; |  | ||||||
| 	} |  | ||||||
| 	function l(i, u) { |  | ||||||
| 		let s = !1; |  | ||||||
| 		for (let h of i) { |  | ||||||
| 			if (u && b(h).then(l), !t.has(h)) |  | ||||||
| 				continue; |  | ||||||
| 			let m = t.get(h); |  | ||||||
| 			m.length_c && (h.dispatchEvent(new Event(g)), m.connected = /* @__PURE__ */ new WeakSet(), m.length_c = 0, m.length_d || t.delete(h), s = !0); |  | ||||||
| 		} |  | ||||||
| 		return s; |  | ||||||
| 	} |  | ||||||
| 	function A(i, u) { |  | ||||||
| 		let s = !1; |  | ||||||
| 		for (let h of i) |  | ||||||
| 			u && b(h).then(A), !(!t.has(h) || !t.get(h).length_d) && ((globalThis.queueMicrotask || setTimeout)(_(h)), s = !0); |  | ||||||
| 		return s; |  | ||||||
| 	} |  | ||||||
| 	function _(i) { |  | ||||||
| 		return () => { |  | ||||||
| 			i.isConnected || (i.dispatchEvent(new Event(y)), t.delete(i)); |  | ||||||
| 		}; |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // src/customElement.js |  | ||||||
| function Dt(t, e, n, r = it) { |  | ||||||
| 	S.push({ |  | ||||||
| 		scope: t, |  | ||||||
| 		host: (...f) => f.length ? f.forEach((d) => d(t)) : t |  | ||||||
| 	}), typeof r == "function" && (r = r.call(t, t)); |  | ||||||
| 	let o = t[x]; |  | ||||||
| 	o || ct(t); |  | ||||||
| 	let c = n.call(t, r); |  | ||||||
| 	return o || t.dispatchEvent(new Event(g)), e.nodeType === 11 && typeof e.mode == "string" && t.addEventListener(y, w.observe(e), { once: !0 }), S.pop(), e.append(c); |  | ||||||
| } |  | ||||||
| function ct(t) { |  | ||||||
| 	return W(t.prototype, "connectedCallback", function(e, n, r) { |  | ||||||
| 		e.apply(n, r), n.dispatchEvent(new Event(g)); |  | ||||||
| 	}), W(t.prototype, "disconnectedCallback", function(e, n, r) { |  | ||||||
| 		e.apply(n, r), (globalThis.queueMicrotask || setTimeout)( |  | ||||||
| 			() => !n.isConnected && n.dispatchEvent(new Event(y)) |  | ||||||
| 		); |  | ||||||
| 	}), W(t.prototype, "attributeChangedCallback", function(e, n, r) { |  | ||||||
| 		let [o, , c] = r; |  | ||||||
| 		n.dispatchEvent(new CustomEvent(D, { |  | ||||||
| 			detail: [o, c] |  | ||||||
| 		})), e.apply(n, r); |  | ||||||
| 	}), t.prototype[x] = !0, t; |  | ||||||
| } |  | ||||||
| function W(t, e, n) { |  | ||||||
| 	t[e] = new Proxy(t[e] || (() => { |  | ||||||
| 	}), { apply: n }); |  | ||||||
| } |  | ||||||
| function it(t) { |  | ||||||
| 	return F(t, (e, n) => e.getAttribute(n)); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // src/events.js |  | ||||||
| function _t(t, e, n) { |  | ||||||
| 	return e || (e = {}), function(o, ...c) { |  | ||||||
| 		n && (c.unshift(o), o = typeof n == "function" ? n() : n); |  | ||||||
| 		let f = c.length ? new CustomEvent(t, Object.assign({ detail: c[0] }, e)) : new Event(t, e); |  | ||||||
| 		return o.dispatchEvent(f); |  | ||||||
| 	}; |  | ||||||
| } |  | ||||||
| function R(t, e, n) { |  | ||||||
| 	return function(o) { |  | ||||||
| 		return o.addEventListener(t, e, n), o; |  | ||||||
| 	}; |  | ||||||
| } |  | ||||||
| var G = (t) => Object.assign({}, typeof t == "object" ? t : null, { once: !0 }); |  | ||||||
| R.connected = function(t, e) { |  | ||||||
| 	return e = G(e), function(r) { |  | ||||||
| 		return r.addEventListener(g, t, e), r[x] ? r : r.isConnected ? (r.dispatchEvent(new Event(g)), r) : (N(e.signal, () => w.offConnected(r, t)) && w.onConnected(r, t), r); |  | ||||||
| 	}; |  | ||||||
| }; |  | ||||||
| R.disconnected = function(t, e) { |  | ||||||
| 	return e = G(e), function(r) { |  | ||||||
| 		return r.addEventListener(y, t, e), r[x] || N(e.signal, () => w.offDisconnected(r, t)) && w.onDisconnected(r, t), r; |  | ||||||
| 	}; |  | ||||||
| }; |  | ||||||
| var j = /* @__PURE__ */ new WeakMap(); |  | ||||||
| R.disconnectedAsAbort = function(t) { |  | ||||||
| 	if (j.has(t)) |  | ||||||
| 		return j.get(t); |  | ||||||
| 	let e = new AbortController(); |  | ||||||
| 	return j.set(t, e), t(R.disconnected(() => e.abort())), e; |  | ||||||
| }; |  | ||||||
| var st = /* @__PURE__ */ new WeakSet(); |  | ||||||
| R.attributeChanged = function(t, e) { |  | ||||||
| 	return typeof e != "object" && (e = {}), function(r) { |  | ||||||
| 		if (r.addEventListener(D, t, e), r[x] || st.has(r) || !a.M) |  | ||||||
| 			return r; |  | ||||||
| 		let o = new a.M(function(f) { |  | ||||||
| 			for (let { attributeName: d, target: p } of f) |  | ||||||
| 				p.dispatchEvent( |  | ||||||
| 					new CustomEvent(D, { detail: [d, p.getAttribute(d)] }) |  | ||||||
| 				); |  | ||||||
| 		}); |  | ||||||
| 		return N(e.signal, () => o.disconnect()) && o.observe(r, { attributes: !0 }), r; |  | ||||||
| 	}; |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| globalThis.dde= { |  | ||||||
| 	assign: O, |  | ||||||
| 	assignAttribute: z, |  | ||||||
| 	chainableAppend: Q, |  | ||||||
| 	classListDeclarative: Y, |  | ||||||
| 	createElement: k, |  | ||||||
| 	createElementNS: gt, |  | ||||||
| 	customElementRender: Dt, |  | ||||||
| 	customElementWithDDE: ct, |  | ||||||
| 	dispatchEvent: _t, |  | ||||||
| 	el: k, |  | ||||||
| 	elNS: gt, |  | ||||||
| 	elementAttribute: tt, |  | ||||||
| 	empty: vt, |  | ||||||
| 	lifecyclesToEvents: ct, |  | ||||||
| 	observedAttributes: it, |  | ||||||
| 	on: R, |  | ||||||
| 	registerReactivity: V, |  | ||||||
| 	scope: S, |  | ||||||
| 	simulateSlots: bt |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| })(); |  | ||||||
							
								
								
									
										948
									
								
								dist/esm-with-signals.d.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										948
									
								
								dist/esm-with-signals.d.ts
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										1502
									
								
								dist/esm-with-signals.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1502
									
								
								dist/esm-with-signals.js
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										860
									
								
								dist/esm-with-signals.min.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										860
									
								
								dist/esm-with-signals.min.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,860 @@ | |||||||
|  | // Generated by dts-bundle-generator v9.5.1 | ||||||
|  |  | ||||||
|  | export interface Signal<V, A> { | ||||||
|  | 	/** The current value of the signal */ | ||||||
|  | 	get(): V; | ||||||
|  | 	/** Set new value of the signal */ | ||||||
|  | 	set(value: V, force?: boolean): V; | ||||||
|  | 	toJSON(): V; | ||||||
|  | 	valueOf(): V; | ||||||
|  | } | ||||||
|  | export type Action<V> = (this: { | ||||||
|  | 	value: V; | ||||||
|  | 	stopPropagation(): void; | ||||||
|  | }, ...a: any[]) => typeof signal._ | void; | ||||||
|  | //type SymbolSignal= Symbol; | ||||||
|  | export type SymbolOnclear = symbol; | ||||||
|  | export type Actions<V> = Record<string | SymbolOnclear, Action<V>>; | ||||||
|  | export type OnListenerOptions = Pick<AddEventListenerOptions, "signal"> & { | ||||||
|  | 	first_time?: boolean; | ||||||
|  | }; | ||||||
|  | export type SElement = Node | Element | DocumentFragment | ddeHTMLElement | ddeSVGElement | ddeDocumentFragment; | ||||||
|  | export interface signal { | ||||||
|  | 	_: Symbol; | ||||||
|  | 	/** | ||||||
|  | 	 * Computations signal. This creates a signal which is computed from other signals. | ||||||
|  | 	 * */ | ||||||
|  | 	<V extends () => any>(computation: V): Signal<ReturnType<V>, {}>; | ||||||
|  | 	/** | ||||||
|  | 	 * Simple example: | ||||||
|  | 	 * ```js | ||||||
|  | 	 * const hello= S("Hello Signal"); | ||||||
|  | 	 * ``` | ||||||
|  | 	 * …simple todo signal: | ||||||
|  | 	 * ```js | ||||||
|  | 	 * const todos= S([], { | ||||||
|  | 	 * 	add(v){ this.value.push(S(v)); }, | ||||||
|  | 	 * 	remove(i){ this.value.splice(i, 1); }, | ||||||
|  | 	 * 	[S.symbols.onclear](){ S.clear(...this.value); }, | ||||||
|  | 	 * }); | ||||||
|  | 	 * ``` | ||||||
|  | 	 * …computed signal: | ||||||
|  | 	 * ```js | ||||||
|  | 	 * const name= S("Jan"); | ||||||
|  | 	 * const surname= S("Andrle"); | ||||||
|  | 	 * const fullname= S(()=> name.get()+" "+surname.get()); | ||||||
|  | 	 * ``` | ||||||
|  | 	 * @param value Initial signal value. Or function computing value from other signals. | ||||||
|  | 	 * @param actions Use to define actions on the signal. Such as add item to the array. | ||||||
|  | 	 *		There is also a reserved function `S.symbol.onclear` which is called when the signal is cleared | ||||||
|  | 	 *		by `S.clear`. | ||||||
|  | 	 * */ | ||||||
|  | 	<V, A extends Actions<V>>(value: V, actions?: A): Signal<V, A>; | ||||||
|  | 	action<S extends Signal<any, Actions<any>>, A extends (S extends Signal<any, infer A> ? A : never), N extends keyof A>(signal: S, name: N, ...params: A[N] extends (...args: infer P) => any ? P : never): void; | ||||||
|  | 	clear(...signals: Signal<any, any>[]): void; | ||||||
|  | 	on<T>(signal: Signal<T, any>, onchange: (a: T) => void, options?: OnListenerOptions): void; | ||||||
|  | 	symbols: { | ||||||
|  | 		//signal: SymbolSignal; | ||||||
|  | 		onclear: SymbolOnclear; | ||||||
|  | 	}; | ||||||
|  | 	/** | ||||||
|  | 	 * Reactive element, which is rendered based on the given signal. | ||||||
|  | 	 * ```js | ||||||
|  | 	 * S.el(signal, value=> value ? el("b", "True") : el("i", "False")); | ||||||
|  | 	 * S.el(listS, list=> list.map(li=> el("li", li))); | ||||||
|  | 	 * ``` | ||||||
|  | 	 * */ | ||||||
|  | 	el<S extends any>(signal: Signal<S, any>, el: (v: S) => SElement | SElement[]): DocumentFragment; | ||||||
|  | 	observedAttributes(custom_element: HTMLElement): Record<string, Signal<string, {}>>; | ||||||
|  | } | ||||||
|  | export const signal: signal; | ||||||
|  | export const S: signal; | ||||||
|  | declare global { | ||||||
|  | 	type ddeSignal<T, A = {}> = Signal<T, A>; | ||||||
|  | 	type ddeAction<V> = Action<V>; | ||||||
|  | 	type ddeActions<V> = Actions<V>; | ||||||
|  | } | ||||||
|  | export type CustomElementTagNameMap = { | ||||||
|  | 	"#text": Text; | ||||||
|  | 	"#comment": Comment; | ||||||
|  | }; | ||||||
|  | export type SupportedElement = HTMLElementTagNameMap[keyof HTMLElementTagNameMap] | SVGElementTagNameMap[keyof SVGElementTagNameMap] | MathMLElementTagNameMap[keyof MathMLElementTagNameMap] | CustomElementTagNameMap[keyof CustomElementTagNameMap]; | ||||||
|  | declare global { | ||||||
|  | 	type ddeComponentAttributes = Record<any, any> | undefined; | ||||||
|  | 	type ddeElementAddon<El extends SupportedElement | DocumentFragment | Node> = (element: El, ...rest: any) => any; | ||||||
|  | 	type ddeString = string | Signal<string, {}>; | ||||||
|  | 	type ddeStringable = ddeString | number | Signal<number, {}>; | ||||||
|  | } | ||||||
|  | export type Host<EL extends SupportedElement> = (...addons: ddeElementAddon<EL>[]) => EL; | ||||||
|  | export type PascalCase = `${Capitalize<string>}${string}`; | ||||||
|  | export type AttrsModified = { | ||||||
|  | 	/** | ||||||
|  | 	 * Use string like in HTML (internally uses `*.setAttribute("style", *)`), or object representation (like DOM API). | ||||||
|  | 	 */ | ||||||
|  | 	style: Partial<CSSStyleDeclaration> | ddeString | Partial<{ | ||||||
|  | 		[K in keyof CSSStyleDeclaration]: Signal<CSSStyleDeclaration[K], {}>; | ||||||
|  | 	}>; | ||||||
|  | 	/** | ||||||
|  | 	 * Provide option to add/remove/toggle CSS clasess (index of object) using 1/0/-1. | ||||||
|  | 	 * In fact `el.classList.toggle(class_name)` for `-1` and `el.classList.toggle(class_name, Boolean(...))` | ||||||
|  | 	 * for others. | ||||||
|  | 	 */ | ||||||
|  | 	classList: Record<string, -1 | 0 | 1 | boolean | Signal<-1 | 0 | 1 | boolean, {}>>; | ||||||
|  | 	/** | ||||||
|  | 	 * Used by the dataset HTML attribute to represent data for custom attributes added to elements. | ||||||
|  | 	 * Values are converted to string (see {@link DOMStringMap}). | ||||||
|  | 	 * | ||||||
|  | 	 * [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMStringMap) | ||||||
|  | 	 * */ | ||||||
|  | 	dataset: Record<string, ddeStringable>; | ||||||
|  | 	/** | ||||||
|  | 	 * Sets `aria-*` simiraly to `dataset` | ||||||
|  | 	 * */ | ||||||
|  | 	ariaset: Record<string, ddeString>; | ||||||
|  | } & Record<`=${string}` | `data${PascalCase}` | `aria${PascalCase}`, ddeString> & Record<`.${string}`, any>; | ||||||
|  | export type _fromElsInterfaces<EL extends SupportedElement> = Omit<EL, keyof AttrsModified>; | ||||||
|  | export type IsReadonly<T, K extends keyof T> = T extends { | ||||||
|  | 	readonly [P in K]: T[K]; | ||||||
|  | } ? true : false; | ||||||
|  | /** | ||||||
|  |  * Just element attributtes | ||||||
|  |  * | ||||||
|  |  * In most cases, you can use native propertie such as | ||||||
|  |  * [MDN WEB/API/Element](https://developer.mozilla.org/en-US/docs/Web/API/Element) and so on | ||||||
|  |  * (e.g. [`Text`](https://developer.mozilla.org/en-US/docs/Web/API/Text)). | ||||||
|  |  * | ||||||
|  |  * There is added support for `data[A-Z].*`/`aria[A-Z].*` to be converted to the kebab-case alternatives. | ||||||
|  |  * @private | ||||||
|  |  */ | ||||||
|  | export type ElementAttributes<T extends SupportedElement> = Partial<{ | ||||||
|  | 	[K in keyof _fromElsInterfaces<T>]: _fromElsInterfaces<T>[K] extends ((...p: any[]) => any) ? _fromElsInterfaces<T>[K] | ((...p: Parameters<_fromElsInterfaces<T>[K]>) => Signal<ReturnType<_fromElsInterfaces<T>[K]>, {}>) : (IsReadonly<_fromElsInterfaces<T>, K> extends false ? _fromElsInterfaces<T>[K] | Signal<_fromElsInterfaces<T>[K], {}> : ddeStringable); | ||||||
|  | } & AttrsModified> & Record<string, any>; | ||||||
|  | export function classListDeclarative<El extends SupportedElement>(element: El, classList: AttrsModified["classList"]): El; | ||||||
|  | export function assign<El extends SupportedElement>(element: El, ...attrs_array: ElementAttributes<El>[]): El; | ||||||
|  | export function assignAttribute<El extends SupportedElement, ATT extends keyof ElementAttributes<El>>(element: El, attr: ATT, value: ElementAttributes<El>[ATT]): ElementAttributes<El>[ATT]; | ||||||
|  | export type ExtendedHTMLElementTagNameMap = HTMLElementTagNameMap & CustomElementTagNameMap; | ||||||
|  | export namespace el { | ||||||
|  | 	/** | ||||||
|  | 	 * Creates a marker comment for elements | ||||||
|  | 	 * | ||||||
|  | 	 * @param attrs - Marker attributes | ||||||
|  | 	 * @param [is_open=false] - Whether the marker is open-ended | ||||||
|  | 	 * @returns Comment node marker | ||||||
|  | 	 */ | ||||||
|  | 	export function mark(attrs: { | ||||||
|  | 		type: "component" | "reactive" | "later"; | ||||||
|  | 		name?: string; | ||||||
|  | 		host?: "this" | "parentElement"; | ||||||
|  | 	}, is_open?: boolean): Comment; | ||||||
|  | } | ||||||
|  | export function chainableAppend<EL extends SupportedElement>(el: EL): EL | ddeHTMLElement; | ||||||
|  | export function el<A extends ddeComponentAttributes, EL extends SupportedElement | ddeDocumentFragment>(component: (attr: A, ...rest: any[]) => EL, attrs?: NoInfer<A>, ...addons: ddeElementAddon<EL>[]): EL extends ddeHTMLElementTagNameMap[keyof ddeHTMLElementTagNameMap] ? EL : (EL extends ddeDocumentFragment ? EL : ddeHTMLElement); | ||||||
|  | export function el<A extends { | ||||||
|  | 	textContent: ddeStringable; | ||||||
|  | }, EL extends SupportedElement | ddeDocumentFragment>(component: (attr: A, ...rest: any[]) => EL, attrs?: NoInfer<A>["textContent"], ...addons: ddeElementAddon<EL>[]): EL extends ddeHTMLElementTagNameMap[keyof ddeHTMLElementTagNameMap] ? EL : (EL extends ddeDocumentFragment ? EL : ddeHTMLElement); | ||||||
|  | export function el<TAG extends keyof ExtendedHTMLElementTagNameMap>(tag_name: TAG, attrs?: ElementAttributes<ExtendedHTMLElementTagNameMap[NoInfer<TAG>]> | ddeStringable, ...addons: ddeElementAddon<ExtendedHTMLElementTagNameMap[NoInfer<TAG>]>[]): TAG extends keyof ddeHTMLElementTagNameMap ? ddeHTMLElementTagNameMap[TAG] : ddeHTMLElement; | ||||||
|  | export function el(tag_name?: "<>"): ddeDocumentFragment; | ||||||
|  | export function el(tag_name: string, attrs?: ElementAttributes<HTMLElement> | ddeStringable, ...addons: ddeElementAddon<HTMLElement>[]): ddeHTMLElement; | ||||||
|  | export function elNS(namespace: "http://www.w3.org/2000/svg"): <TAG extends keyof SVGElementTagNameMap & string, EL extends (TAG extends keyof SVGElementTagNameMap ? SVGElementTagNameMap[TAG] : SVGElement)>(tag_name: TAG, attrs?: ElementAttributes<NoInfer<EL>> | ddeStringable, ...addons: ddeElementAddon<NoInfer<EL>>[]) => TAG extends keyof ddeSVGElementTagNameMap ? ddeSVGElementTagNameMap[TAG] : ddeSVGElement; | ||||||
|  | export function elNS(namespace: "http://www.w3.org/1998/Math/MathML"): <TAG extends keyof MathMLElementTagNameMap & string, EL extends (TAG extends keyof MathMLElementTagNameMap ? MathMLElementTagNameMap[TAG] : MathMLElement)>(tag_name: TAG, attrs?: ddeStringable | Partial<{ | ||||||
|  | 	[key in keyof EL]: EL[key] | Signal<EL[key], {}> | string | number | boolean; | ||||||
|  | }>, ...addons: ddeElementAddon<NoInfer<EL>>[]) => ddeMathMLElement; | ||||||
|  | export function elNS(namespace: string): (tag_name: string, attrs?: string | ddeStringable | Record<string, any>, ...addons: ddeElementAddon<SupportedElement>[]) => SupportedElement; | ||||||
|  | /** Simulate slots for ddeComponents */ | ||||||
|  | export function simulateSlots<EL extends SupportedElement | DocumentFragment>(root: EL): EL; | ||||||
|  | /** | ||||||
|  |  * Simulate slots in Custom Elements without using `shadowRoot`. | ||||||
|  |  * @param el Custom Element root element | ||||||
|  |  * @param body Body of the custom element | ||||||
|  |  * */ | ||||||
|  | export function simulateSlots<EL extends SupportedElement | DocumentFragment>(el: HTMLElement, body: EL): EL; | ||||||
|  | declare function dispatchEvent$1(name: keyof DocumentEventMap | string, host: Host<SupportedElement>): (data?: any) => void; | ||||||
|  | declare function dispatchEvent$1(name: keyof DocumentEventMap | string, options?: EventInit): (element: SupportedElement, data?: any) => void; | ||||||
|  | declare function dispatchEvent$1(name: keyof DocumentEventMap | string, options: EventInit | null, host: Host<SupportedElement>): (data?: any) => void; | ||||||
|  | export interface On { | ||||||
|  | 	/** Listens to the DOM event. See {@link Document.addEventListener} */ | ||||||
|  | 	<Event extends keyof DocumentEventMap, EL extends SupportedElement>(type: Event, listener: (this: EL, ev: DocumentEventMap[Event] & { | ||||||
|  | 		target: EL; | ||||||
|  | 	}) => any, options?: AddEventListenerOptions): ddeElementAddon<EL>; | ||||||
|  | 	<EE extends ddeElementAddon<SupportedElement> = ddeElementAddon<HTMLElement>>(type: string, listener: (this: EE extends ddeElementAddon<infer El> ? El : never, ev: Event | CustomEvent) => any, options?: AddEventListenerOptions): EE; | ||||||
|  | 	/** Listens to the element is connected to the live DOM. In case of custom elements uses [`connectedCallback`](https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_custom_elements#custom_element_lifecycle_callbacks), or {@link MutationObserver} else where */ // editorconfig-checker-disable-line | ||||||
|  | 	connected<EL extends SupportedElement>(listener: (this: EL, event: CustomEvent<NoInfer<EL>>) => any, options?: AddEventListenerOptions): ddeElementAddon<EL>; | ||||||
|  | 	/** Listens to the element is disconnected from the live DOM. In case of custom elements uses [`disconnectedCallback`](https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_custom_elements#custom_element_lifecycle_callbacks), or {@link MutationObserver} else where */ // editorconfig-checker-disable-line | ||||||
|  | 	disconnected<EL extends SupportedElement>(listener: (this: EL, event: CustomEvent<void>) => any, options?: AddEventListenerOptions): ddeElementAddon<EL>; | ||||||
|  | 	/** | ||||||
|  | 	 * Fires after the next tick of the Javascript event loop. | ||||||
|  | 	 * This is handy for example to apply some property depending on the element content: | ||||||
|  | 	 * ```js | ||||||
|  | 	 * const selected= "Z"; | ||||||
|  | 	 * //... | ||||||
|  | 	 * return el("form").append( | ||||||
|  | 	 *		el("select", null, on.defer(e=> e.value=selected)).append( | ||||||
|  | 	 *			el("option", { value: "A", textContent: "A" }), | ||||||
|  | 	 *			//... | ||||||
|  | 	 *			el("option", { value: "Z", textContent: "Z" }), | ||||||
|  | 	 *		), | ||||||
|  | 	 * ); | ||||||
|  | 	 * ``` | ||||||
|  | 	 * */ | ||||||
|  | 	defer<EL extends SupportedElement>(listener: (element: EL) => any): ddeElementAddon<EL>; | ||||||
|  | } | ||||||
|  | export const on: On; | ||||||
|  | export type Scope = { | ||||||
|  | 	scope: Node | Function | Object; | ||||||
|  | 	host: Host<SupportedElement>; | ||||||
|  | 	custom_element: false | HTMLElement; | ||||||
|  | 	prevent: boolean; | ||||||
|  | }; | ||||||
|  | /** Current scope created last time the `el(Function)` was invoke. (Or {@link scope.push}) */ | ||||||
|  | export const scope: { | ||||||
|  | 	current: Scope; | ||||||
|  | 	/** Stops all automatizations. E. g. signals used as attributes in current scope | ||||||
|  | 	 * registers removing these listeners (and clean signal if no other listeners are detected) | ||||||
|  | 	 * on `disconnected` event. */ | ||||||
|  | 	preventDefault<T extends boolean>(prevent: T): T; | ||||||
|  | 	/** | ||||||
|  | 	 * This represents reference to the current host element — `scope.host()`. | ||||||
|  | 	 * It can be also used to register Addon(s) (functions to be called when component is initized) | ||||||
|  | 	 * — `scope.host(on.connected(console.log))`. | ||||||
|  | 	 * */ | ||||||
|  | 	host: Host<SupportedElement>; | ||||||
|  | 	/** | ||||||
|  | 	 * Creates/gets an AbortController that triggers when the element disconnects | ||||||
|  | 	 * */ | ||||||
|  | 	signal: AbortSignal; | ||||||
|  | 	state: Scope[]; | ||||||
|  | 	/** Adds new child scope. All attributes are inherited by default. */ | ||||||
|  | 	push(scope?: Partial<Scope>): ReturnType<Array<Scope>["push"]>; | ||||||
|  | 	/** Adds root scope as a child of the current scope. */ | ||||||
|  | 	pushRoot(): ReturnType<Array<Scope>["push"]>; | ||||||
|  | 	/** Removes last/current child scope. */ | ||||||
|  | 	pop(): ReturnType<Array<Scope>["pop"]>; | ||||||
|  | }; | ||||||
|  | export function customElementRender<EL extends HTMLElement, P extends any = Record<string, string | Signal<string, {}>>>(target: ShadowRoot | EL, render: (props: P) => SupportedElement | DocumentFragment, props?: P | ((el: EL) => P)): EL; | ||||||
|  | export function customElementWithDDE<EL extends (new () => HTMLElement)>(custom_element: EL): EL; | ||||||
|  | export function lifecyclesToEvents<EL extends (new () => HTMLElement)>(custom_element: EL): EL; | ||||||
|  | /** | ||||||
|  |  * This is used primarly for server side rendering. To be sure that all async operations | ||||||
|  |  * are finished before the page is sent to the client. | ||||||
|  |  * ``` | ||||||
|  |  *	// on component | ||||||
|  |  *	function component(){ | ||||||
|  |  *		… | ||||||
|  |  *		queue(fetch(...).then(...)); | ||||||
|  |  *	} | ||||||
|  |  * | ||||||
|  |  * // building the page | ||||||
|  |  * async function build(){ | ||||||
|  |  *		const { component }= await import("./component.js"); | ||||||
|  |  *		document.body.append(el(component)); | ||||||
|  |  *		await queue(); | ||||||
|  |  *		retutn document.body.innerHTML; | ||||||
|  |  *	} | ||||||
|  |  * ``` | ||||||
|  |  * */ | ||||||
|  | export function queue(promise?: Promise<unknown>): Promise<unknown>; | ||||||
|  | /** | ||||||
|  |  * Memoization utility for caching DOM elements to improve performance. | ||||||
|  |  * Used to prevent unnecessary recreation of elements when rendering lists or complex components. | ||||||
|  |  * | ||||||
|  |  * @param key - Unique identifier for the element (usually an ID or unique value) | ||||||
|  |  * @param generator - Function that creates the element | ||||||
|  |  * @returns The cached element if the key exists, otherwise the result of the generator function | ||||||
|  |  * | ||||||
|  |  * @example | ||||||
|  |  * ```ts | ||||||
|  |  * // Within S.el for list rendering | ||||||
|  |  * S.el(itemsSignal, (items, memo) => | ||||||
|  |  *   el("ul").append( | ||||||
|  |  *     ...items.map(item => | ||||||
|  |  *       memo(item.id, () => el(ItemComponent, item)) | ||||||
|  |  *     ) | ||||||
|  |  *   ) | ||||||
|  |  * ) | ||||||
|  |  * ``` | ||||||
|  |  */ | ||||||
|  | export function memo<T>(key: string | number | object, generator: (key: any) => T): T; | ||||||
|  | /** | ||||||
|  |  * Memo namespace containing utility functions for memoization. | ||||||
|  |  */ | ||||||
|  | export namespace memo { | ||||||
|  | 	/** | ||||||
|  | 	 * Checks if an object is a memo scope. | ||||||
|  | 	 * @param obj - The object to check | ||||||
|  | 	 * @returns True if the object is a memo scope | ||||||
|  | 	 */ | ||||||
|  | 	export function isScope(obj: any): boolean; | ||||||
|  | 	/** | ||||||
|  | 	 * Creates a memoized function with optional cleanup support. | ||||||
|  | 	 * | ||||||
|  | 	 * @param fun - The function to memoize | ||||||
|  | 	 * @param options - Configuration options | ||||||
|  | 	 * @param options.signal - AbortSignal for cleanup | ||||||
|  | 	 * @param options.onlyLast - When true, only keeps the cache from the most recent call | ||||||
|  | 	 * @returns A memoized version of the function with a .clear() method | ||||||
|  | 	 * | ||||||
|  | 	 * @example | ||||||
|  | 	 * ```ts | ||||||
|  | 	 * const renderItems = memo.scope(function(items) { | ||||||
|  | 	 *	 return items.map(item => | ||||||
|  | 	 *		 memo(item.id, () => el("div", item.name)) | ||||||
|  | 	 *	 ); | ||||||
|  | 	 * }, { | ||||||
|  | 	 *	 signal: controller.signal, | ||||||
|  | 	 *	 onlyLast: true | ||||||
|  | 	 * }); | ||||||
|  | 	 * ``` | ||||||
|  | 	 */ | ||||||
|  | 	export function scope<F extends Function>(fun: F, options?: { | ||||||
|  | 		signal?: AbortSignal; | ||||||
|  | 		onlyLast?: boolean; | ||||||
|  | 	}): F & { | ||||||
|  | 		clear: () => void; | ||||||
|  | 	}; | ||||||
|  | } | ||||||
|  | /* TypeScript MEH */ | ||||||
|  | declare global { | ||||||
|  | 	type ddeAppend<el> = (...nodes: (Node | string)[]) => el; | ||||||
|  | 	interface ddeDocumentFragment extends DocumentFragment { | ||||||
|  | 		append: ddeAppend<ddeDocumentFragment>; | ||||||
|  | 	} | ||||||
|  | 	interface ddeHTMLElement extends HTMLElement { | ||||||
|  | 		append: ddeAppend<ddeHTMLElement>; | ||||||
|  | 	} | ||||||
|  | 	interface ddeSVGElement extends SVGElement { | ||||||
|  | 		append: ddeAppend<ddeSVGElement>; | ||||||
|  | 	} | ||||||
|  | 	interface ddeMathMLElement extends MathMLElement { | ||||||
|  | 		append: ddeAppend<ddeMathMLElement>; | ||||||
|  | 	} | ||||||
|  | 	interface ddeHTMLElementTagNameMap { | ||||||
|  | 		"a": ddeHTMLAnchorElement; | ||||||
|  | 		"area": ddeHTMLAreaElement; | ||||||
|  | 		"audio": ddeHTMLAudioElement; | ||||||
|  | 		"base": ddeHTMLBaseElement; | ||||||
|  | 		"blockquote": ddeHTMLQuoteElement; | ||||||
|  | 		"body": ddeHTMLBodyElement; | ||||||
|  | 		"br": ddeHTMLBRElement; | ||||||
|  | 		"button": ddeHTMLButtonElement; | ||||||
|  | 		"canvas": ddeHTMLCanvasElement; | ||||||
|  | 		"caption": ddeHTMLTableCaptionElement; | ||||||
|  | 		"col": ddeHTMLTableColElement; | ||||||
|  | 		"colgroup": ddeHTMLTableColElement; | ||||||
|  | 		"data": ddeHTMLDataElement; | ||||||
|  | 		"datalist": ddeHTMLDataListElement; | ||||||
|  | 		"del": ddeHTMLModElement; | ||||||
|  | 		"details": ddeHTMLDetailsElement; | ||||||
|  | 		"dialog": ddeHTMLDialogElement; | ||||||
|  | 		"div": ddeHTMLDivElement; | ||||||
|  | 		"dl": ddeHTMLDListElement; | ||||||
|  | 		"embed": ddeHTMLEmbedElement; | ||||||
|  | 		"fieldset": ddeHTMLFieldSetElement; | ||||||
|  | 		"form": ddeHTMLFormElement; | ||||||
|  | 		"h1": ddeHTMLHeadingElement; | ||||||
|  | 		"h2": ddeHTMLHeadingElement; | ||||||
|  | 		"h3": ddeHTMLHeadingElement; | ||||||
|  | 		"h4": ddeHTMLHeadingElement; | ||||||
|  | 		"h5": ddeHTMLHeadingElement; | ||||||
|  | 		"h6": ddeHTMLHeadingElement; | ||||||
|  | 		"head": ddeHTMLHeadElement; | ||||||
|  | 		"hr": ddeHTMLHRElement; | ||||||
|  | 		"html": ddeHTMLHtmlElement; | ||||||
|  | 		"iframe": ddeHTMLIFrameElement; | ||||||
|  | 		"img": ddeHTMLImageElement; | ||||||
|  | 		"input": ddeHTMLInputElement; | ||||||
|  | 		"ins": ddeHTMLModElement; | ||||||
|  | 		"label": ddeHTMLLabelElement; | ||||||
|  | 		"legend": ddeHTMLLegendElement; | ||||||
|  | 		"li": ddeHTMLLIElement; | ||||||
|  | 		"link": ddeHTMLLinkElement; | ||||||
|  | 		"map": ddeHTMLMapElement; | ||||||
|  | 		"menu": ddeHTMLMenuElement; | ||||||
|  | 		"meta": ddeHTMLMetaElement; | ||||||
|  | 		"meter": ddeHTMLMeterElement; | ||||||
|  | 		"object": ddeHTMLObjectElement; | ||||||
|  | 		"ol": ddeHTMLOListElement; | ||||||
|  | 		"optgroup": ddeHTMLOptGroupElement; | ||||||
|  | 		"option": ddeHTMLOptionElement; | ||||||
|  | 		"output": ddeHTMLOutputElement; | ||||||
|  | 		"p": ddeHTMLParagraphElement; | ||||||
|  | 		"picture": ddeHTMLPictureElement; | ||||||
|  | 		"pre": ddeHTMLPreElement; | ||||||
|  | 		"progress": ddeHTMLProgressElement; | ||||||
|  | 		"q": ddeHTMLQuoteElement; | ||||||
|  | 		"script": ddeHTMLScriptElement; | ||||||
|  | 		"select": ddeHTMLSelectElement; | ||||||
|  | 		"slot": ddeHTMLSlotElement; | ||||||
|  | 		"source": ddeHTMLSourceElement; | ||||||
|  | 		"span": ddeHTMLSpanElement; | ||||||
|  | 		"style": ddeHTMLStyleElement; | ||||||
|  | 		"table": ddeHTMLTableElement; | ||||||
|  | 		"tbody": ddeHTMLTableSectionElement; | ||||||
|  | 		"td": ddeHTMLTableCellElement; | ||||||
|  | 		"template": ddeHTMLTemplateElement; | ||||||
|  | 		"textarea": ddeHTMLTextAreaElement; | ||||||
|  | 		"tfoot": ddeHTMLTableSectionElement; | ||||||
|  | 		"th": ddeHTMLTableCellElement; | ||||||
|  | 		"thead": ddeHTMLTableSectionElement; | ||||||
|  | 		"time": ddeHTMLTimeElement; | ||||||
|  | 		"title": ddeHTMLTitleElement; | ||||||
|  | 		"tr": ddeHTMLTableRowElement; | ||||||
|  | 		"track": ddeHTMLTrackElement; | ||||||
|  | 		"ul": ddeHTMLUListElement; | ||||||
|  | 		"video": ddeHTMLVideoElement; | ||||||
|  | 	} | ||||||
|  | 	interface ddeSVGElementTagNameMap { | ||||||
|  | 		"a": ddeSVGAElement; | ||||||
|  | 		"animate": ddeSVGAnimateElement; | ||||||
|  | 		"animateMotion": ddeSVGAnimateMotionElement; | ||||||
|  | 		"animateTransform": ddeSVGAnimateTransformElement; | ||||||
|  | 		"circle": ddeSVGCircleElement; | ||||||
|  | 		"clipPath": ddeSVGClipPathElement; | ||||||
|  | 		"defs": ddeSVGDefsElement; | ||||||
|  | 		"desc": ddeSVGDescElement; | ||||||
|  | 		"ellipse": ddeSVGEllipseElement; | ||||||
|  | 		"feBlend": ddeSVGFEBlendElement; | ||||||
|  | 		"feColorMatrix": ddeSVGFEColorMatrixElement; | ||||||
|  | 		"feComponentTransfer": ddeSVGFEComponentTransferElement; | ||||||
|  | 		"feComposite": ddeSVGFECompositeElement; | ||||||
|  | 		"feConvolveMatrix": ddeSVGFEConvolveMatrixElement; | ||||||
|  | 		"feDiffuseLighting": ddeSVGFEDiffuseLightingElement; | ||||||
|  | 		"feDisplacementMap": ddeSVGFEDisplacementMapElement; | ||||||
|  | 		"feDistantLight": ddeSVGFEDistantLightElement; | ||||||
|  | 		"feDropShadow": ddeSVGFEDropShadowElement; | ||||||
|  | 		"feFlood": ddeSVGFEFloodElement; | ||||||
|  | 		"feFuncA": ddeSVGFEFuncAElement; | ||||||
|  | 		"feFuncB": ddeSVGFEFuncBElement; | ||||||
|  | 		"feFuncG": ddeSVGFEFuncGElement; | ||||||
|  | 		"feFuncR": ddeSVGFEFuncRElement; | ||||||
|  | 		"feGaussianBlur": ddeSVGFEGaussianBlurElement; | ||||||
|  | 		"feImage": ddeSVGFEImageElement; | ||||||
|  | 		"feMerge": ddeSVGFEMergeElement; | ||||||
|  | 		"feMergeNode": ddeSVGFEMergeNodeElement; | ||||||
|  | 		"feMorphology": ddeSVGFEMorphologyElement; | ||||||
|  | 		"feOffset": ddeSVGFEOffsetElement; | ||||||
|  | 		"fePointLight": ddeSVGFEPointLightElement; | ||||||
|  | 		"feSpecularLighting": ddeSVGFESpecularLightingElement; | ||||||
|  | 		"feSpotLight": ddeSVGFESpotLightElement; | ||||||
|  | 		"feTile": ddeSVGFETileElement; | ||||||
|  | 		"feTurbulence": ddeSVGFETurbulenceElement; | ||||||
|  | 		"filter": ddeSVGFilterElement; | ||||||
|  | 		"foreignObject": ddeSVGForeignObjectElement; | ||||||
|  | 		"g": ddeSVGGElement; | ||||||
|  | 		"image": ddeSVGImageElement; | ||||||
|  | 		"line": ddeSVGLineElement; | ||||||
|  | 		"linearGradient": ddeSVGLinearGradientElement; | ||||||
|  | 		"marker": ddeSVGMarkerElement; | ||||||
|  | 		"mask": ddeSVGMaskElement; | ||||||
|  | 		"metadata": ddeSVGMetadataElement; | ||||||
|  | 		"mpath": ddeSVGMPathElement; | ||||||
|  | 		"path": ddeSVGPathElement; | ||||||
|  | 		"pattern": ddeSVGPatternElement; | ||||||
|  | 		"polygon": ddeSVGPolygonElement; | ||||||
|  | 		"polyline": ddeSVGPolylineElement; | ||||||
|  | 		"radialGradient": ddeSVGRadialGradientElement; | ||||||
|  | 		"rect": ddeSVGRectElement; | ||||||
|  | 		"script": ddeSVGScriptElement; | ||||||
|  | 		"set": ddeSVGSetElement; | ||||||
|  | 		"stop": ddeSVGStopElement; | ||||||
|  | 		"style": ddeSVGStyleElement; | ||||||
|  | 		"svg": ddeSVGSVGElement; | ||||||
|  | 		"switch": ddeSVGSwitchElement; | ||||||
|  | 		"symbol": ddeSVGSymbolElement; | ||||||
|  | 		"text": ddeSVGTextElement; | ||||||
|  | 		"textPath": ddeSVGTextPathElement; | ||||||
|  | 		"title": ddeSVGTitleElement; | ||||||
|  | 		"tspan": ddeSVGTSpanElement; | ||||||
|  | 		"use": ddeSVGUseElement; | ||||||
|  | 		"view": ddeSVGViewElement; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | // editorconfig-checker-disable | ||||||
|  | export interface ddeHTMLAnchorElement extends HTMLAnchorElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLAnchorElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLAreaElement extends HTMLAreaElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLAreaElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLAudioElement extends HTMLAudioElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLAudioElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLBaseElement extends HTMLBaseElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLBaseElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLQuoteElement extends HTMLQuoteElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLQuoteElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLBodyElement extends HTMLBodyElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLBodyElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLBRElement extends HTMLBRElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLBRElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLButtonElement extends HTMLButtonElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLButtonElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLCanvasElement extends HTMLCanvasElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLCanvasElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLTableCaptionElement extends HTMLTableCaptionElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLTableCaptionElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLTableColElement extends HTMLTableColElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLTableColElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLTableColElement extends HTMLTableColElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLTableColElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLDataElement extends HTMLDataElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLDataElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLDataListElement extends HTMLDataListElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLDataListElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLModElement extends HTMLModElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLModElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLDetailsElement extends HTMLDetailsElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLDetailsElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLDialogElement extends HTMLDialogElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLDialogElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLDivElement extends HTMLDivElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLDivElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLDListElement extends HTMLDListElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLDListElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLEmbedElement extends HTMLEmbedElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLEmbedElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLFieldSetElement extends HTMLFieldSetElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLFieldSetElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLFormElement extends HTMLFormElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLFormElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLHeadingElement extends HTMLHeadingElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLHeadingElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLHeadElement extends HTMLHeadElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLHeadElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLHRElement extends HTMLHRElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLHRElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLHtmlElement extends HTMLHtmlElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLHtmlElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLIFrameElement extends HTMLIFrameElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLIFrameElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLImageElement extends HTMLImageElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLImageElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLInputElement extends HTMLInputElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLInputElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLLabelElement extends HTMLLabelElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLLabelElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLLegendElement extends HTMLLegendElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLLegendElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLLIElement extends HTMLLIElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLLIElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLLinkElement extends HTMLLinkElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLLinkElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLMapElement extends HTMLMapElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLMapElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLMenuElement extends HTMLMenuElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLMenuElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLMetaElement extends HTMLMetaElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLMetaElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLMeterElement extends HTMLMeterElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLMeterElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLObjectElement extends HTMLObjectElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLObjectElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLOListElement extends HTMLOListElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLOListElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLOptGroupElement extends HTMLOptGroupElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLOptGroupElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLOptionElement extends HTMLOptionElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLOptionElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLOutputElement extends HTMLOutputElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLOutputElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLParagraphElement extends HTMLParagraphElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLParagraphElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLPictureElement extends HTMLPictureElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLPictureElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLPreElement extends HTMLPreElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLPreElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLProgressElement extends HTMLProgressElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLProgressElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLScriptElement extends HTMLScriptElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLScriptElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLSelectElement extends HTMLSelectElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLSelectElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLSlotElement extends HTMLSlotElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLSlotElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLSourceElement extends HTMLSourceElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLSourceElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLSpanElement extends HTMLSpanElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLSpanElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLStyleElement extends HTMLStyleElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLStyleElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLTableElement extends HTMLTableElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLTableElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLTableSectionElement extends HTMLTableSectionElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLTableSectionElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLTableCellElement extends HTMLTableCellElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLTableCellElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLTemplateElement extends HTMLTemplateElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLTemplateElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLTextAreaElement extends HTMLTextAreaElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLTextAreaElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLTableCellElement extends HTMLTableCellElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLTableCellElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLTimeElement extends HTMLTimeElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLTimeElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLTitleElement extends HTMLTitleElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLTitleElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLTableRowElement extends HTMLTableRowElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLTableRowElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLTrackElement extends HTMLTrackElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLTrackElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLUListElement extends HTMLUListElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLUListElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLVideoElement extends HTMLVideoElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLVideoElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGAElement extends SVGAElement { | ||||||
|  | 	append: ddeAppend<ddeSVGAElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGAnimateElement extends SVGAnimateElement { | ||||||
|  | 	append: ddeAppend<ddeSVGAnimateElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGAnimateMotionElement extends SVGAnimateMotionElement { | ||||||
|  | 	append: ddeAppend<ddeSVGAnimateMotionElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGAnimateTransformElement extends SVGAnimateTransformElement { | ||||||
|  | 	append: ddeAppend<ddeSVGAnimateTransformElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGCircleElement extends SVGCircleElement { | ||||||
|  | 	append: ddeAppend<ddeSVGCircleElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGClipPathElement extends SVGClipPathElement { | ||||||
|  | 	append: ddeAppend<ddeSVGClipPathElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGDefsElement extends SVGDefsElement { | ||||||
|  | 	append: ddeAppend<ddeSVGDefsElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGDescElement extends SVGDescElement { | ||||||
|  | 	append: ddeAppend<ddeSVGDescElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGEllipseElement extends SVGEllipseElement { | ||||||
|  | 	append: ddeAppend<ddeSVGEllipseElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEBlendElement extends SVGFEBlendElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEBlendElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEColorMatrixElement extends SVGFEColorMatrixElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEColorMatrixElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEComponentTransferElement extends SVGFEComponentTransferElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEComponentTransferElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFECompositeElement extends SVGFECompositeElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFECompositeElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEConvolveMatrixElement extends SVGFEConvolveMatrixElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEConvolveMatrixElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEDiffuseLightingElement extends SVGFEDiffuseLightingElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEDiffuseLightingElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEDisplacementMapElement extends SVGFEDisplacementMapElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEDisplacementMapElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEDistantLightElement extends SVGFEDistantLightElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEDistantLightElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEDropShadowElement extends SVGFEDropShadowElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEDropShadowElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEFloodElement extends SVGFEFloodElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEFloodElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEFuncAElement extends SVGFEFuncAElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEFuncAElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEFuncBElement extends SVGFEFuncBElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEFuncBElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEFuncGElement extends SVGFEFuncGElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEFuncGElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEFuncRElement extends SVGFEFuncRElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEFuncRElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEGaussianBlurElement extends SVGFEGaussianBlurElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEGaussianBlurElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEImageElement extends SVGFEImageElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEImageElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEMergeElement extends SVGFEMergeElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEMergeElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEMergeNodeElement extends SVGFEMergeNodeElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEMergeNodeElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEMorphologyElement extends SVGFEMorphologyElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEMorphologyElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEOffsetElement extends SVGFEOffsetElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEOffsetElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEPointLightElement extends SVGFEPointLightElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEPointLightElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFESpecularLightingElement extends SVGFESpecularLightingElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFESpecularLightingElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFESpotLightElement extends SVGFESpotLightElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFESpotLightElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFETileElement extends SVGFETileElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFETileElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFETurbulenceElement extends SVGFETurbulenceElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFETurbulenceElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFilterElement extends SVGFilterElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFilterElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGForeignObjectElement extends SVGForeignObjectElement { | ||||||
|  | 	append: ddeAppend<ddeSVGForeignObjectElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGGElement extends SVGGElement { | ||||||
|  | 	append: ddeAppend<ddeSVGGElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGImageElement extends SVGImageElement { | ||||||
|  | 	append: ddeAppend<ddeSVGImageElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGLineElement extends SVGLineElement { | ||||||
|  | 	append: ddeAppend<ddeSVGLineElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGLinearGradientElement extends SVGLinearGradientElement { | ||||||
|  | 	append: ddeAppend<ddeSVGLinearGradientElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGMarkerElement extends SVGMarkerElement { | ||||||
|  | 	append: ddeAppend<ddeSVGMarkerElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGMaskElement extends SVGMaskElement { | ||||||
|  | 	append: ddeAppend<ddeSVGMaskElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGMetadataElement extends SVGMetadataElement { | ||||||
|  | 	append: ddeAppend<ddeSVGMetadataElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGMPathElement extends SVGMPathElement { | ||||||
|  | 	append: ddeAppend<ddeSVGMPathElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGPathElement extends SVGPathElement { | ||||||
|  | 	append: ddeAppend<ddeSVGPathElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGPatternElement extends SVGPatternElement { | ||||||
|  | 	append: ddeAppend<ddeSVGPatternElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGPolygonElement extends SVGPolygonElement { | ||||||
|  | 	append: ddeAppend<ddeSVGPolygonElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGPolylineElement extends SVGPolylineElement { | ||||||
|  | 	append: ddeAppend<ddeSVGPolylineElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGRadialGradientElement extends SVGRadialGradientElement { | ||||||
|  | 	append: ddeAppend<ddeSVGRadialGradientElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGRectElement extends SVGRectElement { | ||||||
|  | 	append: ddeAppend<ddeSVGRectElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGScriptElement extends SVGScriptElement { | ||||||
|  | 	append: ddeAppend<ddeSVGScriptElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGSetElement extends SVGSetElement { | ||||||
|  | 	append: ddeAppend<ddeSVGSetElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGStopElement extends SVGStopElement { | ||||||
|  | 	append: ddeAppend<ddeSVGStopElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGStyleElement extends SVGStyleElement { | ||||||
|  | 	append: ddeAppend<ddeSVGStyleElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGSVGElement extends SVGSVGElement { | ||||||
|  | 	append: ddeAppend<ddeSVGSVGElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGSwitchElement extends SVGSwitchElement { | ||||||
|  | 	append: ddeAppend<ddeSVGSwitchElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGSymbolElement extends SVGSymbolElement { | ||||||
|  | 	append: ddeAppend<ddeSVGSymbolElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGTextElement extends SVGTextElement { | ||||||
|  | 	append: ddeAppend<ddeSVGTextElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGTextPathElement extends SVGTextPathElement { | ||||||
|  | 	append: ddeAppend<ddeSVGTextPathElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGTitleElement extends SVGTitleElement { | ||||||
|  | 	append: ddeAppend<ddeSVGTitleElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGTSpanElement extends SVGTSpanElement { | ||||||
|  | 	append: ddeAppend<ddeSVGTSpanElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGUseElement extends SVGUseElement { | ||||||
|  | 	append: ddeAppend<ddeSVGUseElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGViewElement extends SVGViewElement { | ||||||
|  | 	append: ddeAppend<ddeSVGViewElement>; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | export { | ||||||
|  | 	dispatchEvent$1 as dispatchEvent, | ||||||
|  | 	el as createElement, | ||||||
|  | 	elNS as createElementNS, | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | export {}; | ||||||
							
								
								
									
										3
									
								
								dist/esm-with-signals.min.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								dist/esm-with-signals.min.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										951
									
								
								dist/esm.d.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										951
									
								
								dist/esm.d.ts
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										1038
									
								
								dist/esm.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1038
									
								
								dist/esm.js
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										859
									
								
								dist/esm.min.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										859
									
								
								dist/esm.min.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,859 @@ | |||||||
|  | // Generated by dts-bundle-generator v9.5.1 | ||||||
|  |  | ||||||
|  | export interface Signal<V, A> { | ||||||
|  | 	/** The current value of the signal */ | ||||||
|  | 	get(): V; | ||||||
|  | 	/** Set new value of the signal */ | ||||||
|  | 	set(value: V, force?: boolean): V; | ||||||
|  | 	toJSON(): V; | ||||||
|  | 	valueOf(): V; | ||||||
|  | } | ||||||
|  | export type Action<V> = (this: { | ||||||
|  | 	value: V; | ||||||
|  | 	stopPropagation(): void; | ||||||
|  | }, ...a: any[]) => typeof signal._ | void; | ||||||
|  | //type SymbolSignal= Symbol; | ||||||
|  | export type SymbolOnclear = symbol; | ||||||
|  | export type Actions<V> = Record<string | SymbolOnclear, Action<V>>; | ||||||
|  | export type OnListenerOptions = Pick<AddEventListenerOptions, "signal"> & { | ||||||
|  | 	first_time?: boolean; | ||||||
|  | }; | ||||||
|  | export type SElement = Node | Element | DocumentFragment | ddeHTMLElement | ddeSVGElement | ddeDocumentFragment; | ||||||
|  | export interface signal { | ||||||
|  | 	_: Symbol; | ||||||
|  | 	/** | ||||||
|  | 	 * Computations signal. This creates a signal which is computed from other signals. | ||||||
|  | 	 * */ | ||||||
|  | 	<V extends () => any>(computation: V): Signal<ReturnType<V>, {}>; | ||||||
|  | 	/** | ||||||
|  | 	 * Simple example: | ||||||
|  | 	 * ```js | ||||||
|  | 	 * const hello= S("Hello Signal"); | ||||||
|  | 	 * ``` | ||||||
|  | 	 * …simple todo signal: | ||||||
|  | 	 * ```js | ||||||
|  | 	 * const todos= S([], { | ||||||
|  | 	 * 	add(v){ this.value.push(S(v)); }, | ||||||
|  | 	 * 	remove(i){ this.value.splice(i, 1); }, | ||||||
|  | 	 * 	[S.symbols.onclear](){ S.clear(...this.value); }, | ||||||
|  | 	 * }); | ||||||
|  | 	 * ``` | ||||||
|  | 	 * …computed signal: | ||||||
|  | 	 * ```js | ||||||
|  | 	 * const name= S("Jan"); | ||||||
|  | 	 * const surname= S("Andrle"); | ||||||
|  | 	 * const fullname= S(()=> name.get()+" "+surname.get()); | ||||||
|  | 	 * ``` | ||||||
|  | 	 * @param value Initial signal value. Or function computing value from other signals. | ||||||
|  | 	 * @param actions Use to define actions on the signal. Such as add item to the array. | ||||||
|  | 	 *		There is also a reserved function `S.symbol.onclear` which is called when the signal is cleared | ||||||
|  | 	 *		by `S.clear`. | ||||||
|  | 	 * */ | ||||||
|  | 	<V, A extends Actions<V>>(value: V, actions?: A): Signal<V, A>; | ||||||
|  | 	action<S extends Signal<any, Actions<any>>, A extends (S extends Signal<any, infer A> ? A : never), N extends keyof A>(signal: S, name: N, ...params: A[N] extends (...args: infer P) => any ? P : never): void; | ||||||
|  | 	clear(...signals: Signal<any, any>[]): void; | ||||||
|  | 	on<T>(signal: Signal<T, any>, onchange: (a: T) => void, options?: OnListenerOptions): void; | ||||||
|  | 	symbols: { | ||||||
|  | 		//signal: SymbolSignal; | ||||||
|  | 		onclear: SymbolOnclear; | ||||||
|  | 	}; | ||||||
|  | 	/** | ||||||
|  | 	 * Reactive element, which is rendered based on the given signal. | ||||||
|  | 	 * ```js | ||||||
|  | 	 * S.el(signal, value=> value ? el("b", "True") : el("i", "False")); | ||||||
|  | 	 * S.el(listS, list=> list.map(li=> el("li", li))); | ||||||
|  | 	 * ``` | ||||||
|  | 	 * */ | ||||||
|  | 	el<S extends any>(signal: Signal<S, any>, el: (v: S) => SElement | SElement[]): DocumentFragment; | ||||||
|  | 	observedAttributes(custom_element: HTMLElement): Record<string, Signal<string, {}>>; | ||||||
|  | } | ||||||
|  | declare const signal: signal; | ||||||
|  | declare global { | ||||||
|  | 	type ddeSignal<T, A = {}> = Signal<T, A>; | ||||||
|  | 	type ddeAction<V> = Action<V>; | ||||||
|  | 	type ddeActions<V> = Actions<V>; | ||||||
|  | } | ||||||
|  | export type CustomElementTagNameMap = { | ||||||
|  | 	"#text": Text; | ||||||
|  | 	"#comment": Comment; | ||||||
|  | }; | ||||||
|  | export type SupportedElement = HTMLElementTagNameMap[keyof HTMLElementTagNameMap] | SVGElementTagNameMap[keyof SVGElementTagNameMap] | MathMLElementTagNameMap[keyof MathMLElementTagNameMap] | CustomElementTagNameMap[keyof CustomElementTagNameMap]; | ||||||
|  | declare global { | ||||||
|  | 	type ddeComponentAttributes = Record<any, any> | undefined; | ||||||
|  | 	type ddeElementAddon<El extends SupportedElement | DocumentFragment | Node> = (element: El, ...rest: any) => any; | ||||||
|  | 	type ddeString = string | Signal<string, {}>; | ||||||
|  | 	type ddeStringable = ddeString | number | Signal<number, {}>; | ||||||
|  | } | ||||||
|  | export type Host<EL extends SupportedElement> = (...addons: ddeElementAddon<EL>[]) => EL; | ||||||
|  | export type PascalCase = `${Capitalize<string>}${string}`; | ||||||
|  | export type AttrsModified = { | ||||||
|  | 	/** | ||||||
|  | 	 * Use string like in HTML (internally uses `*.setAttribute("style", *)`), or object representation (like DOM API). | ||||||
|  | 	 */ | ||||||
|  | 	style: Partial<CSSStyleDeclaration> | ddeString | Partial<{ | ||||||
|  | 		[K in keyof CSSStyleDeclaration]: Signal<CSSStyleDeclaration[K], {}>; | ||||||
|  | 	}>; | ||||||
|  | 	/** | ||||||
|  | 	 * Provide option to add/remove/toggle CSS clasess (index of object) using 1/0/-1. | ||||||
|  | 	 * In fact `el.classList.toggle(class_name)` for `-1` and `el.classList.toggle(class_name, Boolean(...))` | ||||||
|  | 	 * for others. | ||||||
|  | 	 */ | ||||||
|  | 	classList: Record<string, -1 | 0 | 1 | boolean | Signal<-1 | 0 | 1 | boolean, {}>>; | ||||||
|  | 	/** | ||||||
|  | 	 * Used by the dataset HTML attribute to represent data for custom attributes added to elements. | ||||||
|  | 	 * Values are converted to string (see {@link DOMStringMap}). | ||||||
|  | 	 * | ||||||
|  | 	 * [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMStringMap) | ||||||
|  | 	 * */ | ||||||
|  | 	dataset: Record<string, ddeStringable>; | ||||||
|  | 	/** | ||||||
|  | 	 * Sets `aria-*` simiraly to `dataset` | ||||||
|  | 	 * */ | ||||||
|  | 	ariaset: Record<string, ddeString>; | ||||||
|  | } & Record<`=${string}` | `data${PascalCase}` | `aria${PascalCase}`, ddeString> & Record<`.${string}`, any>; | ||||||
|  | export type _fromElsInterfaces<EL extends SupportedElement> = Omit<EL, keyof AttrsModified>; | ||||||
|  | export type IsReadonly<T, K extends keyof T> = T extends { | ||||||
|  | 	readonly [P in K]: T[K]; | ||||||
|  | } ? true : false; | ||||||
|  | /** | ||||||
|  |  * Just element attributtes | ||||||
|  |  * | ||||||
|  |  * In most cases, you can use native propertie such as | ||||||
|  |  * [MDN WEB/API/Element](https://developer.mozilla.org/en-US/docs/Web/API/Element) and so on | ||||||
|  |  * (e.g. [`Text`](https://developer.mozilla.org/en-US/docs/Web/API/Text)). | ||||||
|  |  * | ||||||
|  |  * There is added support for `data[A-Z].*`/`aria[A-Z].*` to be converted to the kebab-case alternatives. | ||||||
|  |  * @private | ||||||
|  |  */ | ||||||
|  | export type ElementAttributes<T extends SupportedElement> = Partial<{ | ||||||
|  | 	[K in keyof _fromElsInterfaces<T>]: _fromElsInterfaces<T>[K] extends ((...p: any[]) => any) ? _fromElsInterfaces<T>[K] | ((...p: Parameters<_fromElsInterfaces<T>[K]>) => Signal<ReturnType<_fromElsInterfaces<T>[K]>, {}>) : (IsReadonly<_fromElsInterfaces<T>, K> extends false ? _fromElsInterfaces<T>[K] | Signal<_fromElsInterfaces<T>[K], {}> : ddeStringable); | ||||||
|  | } & AttrsModified> & Record<string, any>; | ||||||
|  | export function classListDeclarative<El extends SupportedElement>(element: El, classList: AttrsModified["classList"]): El; | ||||||
|  | export function assign<El extends SupportedElement>(element: El, ...attrs_array: ElementAttributes<El>[]): El; | ||||||
|  | export function assignAttribute<El extends SupportedElement, ATT extends keyof ElementAttributes<El>>(element: El, attr: ATT, value: ElementAttributes<El>[ATT]): ElementAttributes<El>[ATT]; | ||||||
|  | export type ExtendedHTMLElementTagNameMap = HTMLElementTagNameMap & CustomElementTagNameMap; | ||||||
|  | export namespace el { | ||||||
|  | 	/** | ||||||
|  | 	 * Creates a marker comment for elements | ||||||
|  | 	 * | ||||||
|  | 	 * @param attrs - Marker attributes | ||||||
|  | 	 * @param [is_open=false] - Whether the marker is open-ended | ||||||
|  | 	 * @returns Comment node marker | ||||||
|  | 	 */ | ||||||
|  | 	export function mark(attrs: { | ||||||
|  | 		type: "component" | "reactive" | "later"; | ||||||
|  | 		name?: string; | ||||||
|  | 		host?: "this" | "parentElement"; | ||||||
|  | 	}, is_open?: boolean): Comment; | ||||||
|  | } | ||||||
|  | export function chainableAppend<EL extends SupportedElement>(el: EL): EL | ddeHTMLElement; | ||||||
|  | export function el<A extends ddeComponentAttributes, EL extends SupportedElement | ddeDocumentFragment>(component: (attr: A, ...rest: any[]) => EL, attrs?: NoInfer<A>, ...addons: ddeElementAddon<EL>[]): EL extends ddeHTMLElementTagNameMap[keyof ddeHTMLElementTagNameMap] ? EL : (EL extends ddeDocumentFragment ? EL : ddeHTMLElement); | ||||||
|  | export function el<A extends { | ||||||
|  | 	textContent: ddeStringable; | ||||||
|  | }, EL extends SupportedElement | ddeDocumentFragment>(component: (attr: A, ...rest: any[]) => EL, attrs?: NoInfer<A>["textContent"], ...addons: ddeElementAddon<EL>[]): EL extends ddeHTMLElementTagNameMap[keyof ddeHTMLElementTagNameMap] ? EL : (EL extends ddeDocumentFragment ? EL : ddeHTMLElement); | ||||||
|  | export function el<TAG extends keyof ExtendedHTMLElementTagNameMap>(tag_name: TAG, attrs?: ElementAttributes<ExtendedHTMLElementTagNameMap[NoInfer<TAG>]> | ddeStringable, ...addons: ddeElementAddon<ExtendedHTMLElementTagNameMap[NoInfer<TAG>]>[]): TAG extends keyof ddeHTMLElementTagNameMap ? ddeHTMLElementTagNameMap[TAG] : ddeHTMLElement; | ||||||
|  | export function el(tag_name?: "<>"): ddeDocumentFragment; | ||||||
|  | export function el(tag_name: string, attrs?: ElementAttributes<HTMLElement> | ddeStringable, ...addons: ddeElementAddon<HTMLElement>[]): ddeHTMLElement; | ||||||
|  | export function elNS(namespace: "http://www.w3.org/2000/svg"): <TAG extends keyof SVGElementTagNameMap & string, EL extends (TAG extends keyof SVGElementTagNameMap ? SVGElementTagNameMap[TAG] : SVGElement)>(tag_name: TAG, attrs?: ElementAttributes<NoInfer<EL>> | ddeStringable, ...addons: ddeElementAddon<NoInfer<EL>>[]) => TAG extends keyof ddeSVGElementTagNameMap ? ddeSVGElementTagNameMap[TAG] : ddeSVGElement; | ||||||
|  | export function elNS(namespace: "http://www.w3.org/1998/Math/MathML"): <TAG extends keyof MathMLElementTagNameMap & string, EL extends (TAG extends keyof MathMLElementTagNameMap ? MathMLElementTagNameMap[TAG] : MathMLElement)>(tag_name: TAG, attrs?: ddeStringable | Partial<{ | ||||||
|  | 	[key in keyof EL]: EL[key] | Signal<EL[key], {}> | string | number | boolean; | ||||||
|  | }>, ...addons: ddeElementAddon<NoInfer<EL>>[]) => ddeMathMLElement; | ||||||
|  | export function elNS(namespace: string): (tag_name: string, attrs?: string | ddeStringable | Record<string, any>, ...addons: ddeElementAddon<SupportedElement>[]) => SupportedElement; | ||||||
|  | /** Simulate slots for ddeComponents */ | ||||||
|  | export function simulateSlots<EL extends SupportedElement | DocumentFragment>(root: EL): EL; | ||||||
|  | /** | ||||||
|  |  * Simulate slots in Custom Elements without using `shadowRoot`. | ||||||
|  |  * @param el Custom Element root element | ||||||
|  |  * @param body Body of the custom element | ||||||
|  |  * */ | ||||||
|  | export function simulateSlots<EL extends SupportedElement | DocumentFragment>(el: HTMLElement, body: EL): EL; | ||||||
|  | declare function dispatchEvent$1(name: keyof DocumentEventMap | string, host: Host<SupportedElement>): (data?: any) => void; | ||||||
|  | declare function dispatchEvent$1(name: keyof DocumentEventMap | string, options?: EventInit): (element: SupportedElement, data?: any) => void; | ||||||
|  | declare function dispatchEvent$1(name: keyof DocumentEventMap | string, options: EventInit | null, host: Host<SupportedElement>): (data?: any) => void; | ||||||
|  | export interface On { | ||||||
|  | 	/** Listens to the DOM event. See {@link Document.addEventListener} */ | ||||||
|  | 	<Event extends keyof DocumentEventMap, EL extends SupportedElement>(type: Event, listener: (this: EL, ev: DocumentEventMap[Event] & { | ||||||
|  | 		target: EL; | ||||||
|  | 	}) => any, options?: AddEventListenerOptions): ddeElementAddon<EL>; | ||||||
|  | 	<EE extends ddeElementAddon<SupportedElement> = ddeElementAddon<HTMLElement>>(type: string, listener: (this: EE extends ddeElementAddon<infer El> ? El : never, ev: Event | CustomEvent) => any, options?: AddEventListenerOptions): EE; | ||||||
|  | 	/** Listens to the element is connected to the live DOM. In case of custom elements uses [`connectedCallback`](https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_custom_elements#custom_element_lifecycle_callbacks), or {@link MutationObserver} else where */ // editorconfig-checker-disable-line | ||||||
|  | 	connected<EL extends SupportedElement>(listener: (this: EL, event: CustomEvent<NoInfer<EL>>) => any, options?: AddEventListenerOptions): ddeElementAddon<EL>; | ||||||
|  | 	/** Listens to the element is disconnected from the live DOM. In case of custom elements uses [`disconnectedCallback`](https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_custom_elements#custom_element_lifecycle_callbacks), or {@link MutationObserver} else where */ // editorconfig-checker-disable-line | ||||||
|  | 	disconnected<EL extends SupportedElement>(listener: (this: EL, event: CustomEvent<void>) => any, options?: AddEventListenerOptions): ddeElementAddon<EL>; | ||||||
|  | 	/** | ||||||
|  | 	 * Fires after the next tick of the Javascript event loop. | ||||||
|  | 	 * This is handy for example to apply some property depending on the element content: | ||||||
|  | 	 * ```js | ||||||
|  | 	 * const selected= "Z"; | ||||||
|  | 	 * //... | ||||||
|  | 	 * return el("form").append( | ||||||
|  | 	 *		el("select", null, on.defer(e=> e.value=selected)).append( | ||||||
|  | 	 *			el("option", { value: "A", textContent: "A" }), | ||||||
|  | 	 *			//... | ||||||
|  | 	 *			el("option", { value: "Z", textContent: "Z" }), | ||||||
|  | 	 *		), | ||||||
|  | 	 * ); | ||||||
|  | 	 * ``` | ||||||
|  | 	 * */ | ||||||
|  | 	defer<EL extends SupportedElement>(listener: (element: EL) => any): ddeElementAddon<EL>; | ||||||
|  | } | ||||||
|  | export const on: On; | ||||||
|  | export type Scope = { | ||||||
|  | 	scope: Node | Function | Object; | ||||||
|  | 	host: Host<SupportedElement>; | ||||||
|  | 	custom_element: false | HTMLElement; | ||||||
|  | 	prevent: boolean; | ||||||
|  | }; | ||||||
|  | /** Current scope created last time the `el(Function)` was invoke. (Or {@link scope.push}) */ | ||||||
|  | export const scope: { | ||||||
|  | 	current: Scope; | ||||||
|  | 	/** Stops all automatizations. E. g. signals used as attributes in current scope | ||||||
|  | 	 * registers removing these listeners (and clean signal if no other listeners are detected) | ||||||
|  | 	 * on `disconnected` event. */ | ||||||
|  | 	preventDefault<T extends boolean>(prevent: T): T; | ||||||
|  | 	/** | ||||||
|  | 	 * This represents reference to the current host element — `scope.host()`. | ||||||
|  | 	 * It can be also used to register Addon(s) (functions to be called when component is initized) | ||||||
|  | 	 * — `scope.host(on.connected(console.log))`. | ||||||
|  | 	 * */ | ||||||
|  | 	host: Host<SupportedElement>; | ||||||
|  | 	/** | ||||||
|  | 	 * Creates/gets an AbortController that triggers when the element disconnects | ||||||
|  | 	 * */ | ||||||
|  | 	signal: AbortSignal; | ||||||
|  | 	state: Scope[]; | ||||||
|  | 	/** Adds new child scope. All attributes are inherited by default. */ | ||||||
|  | 	push(scope?: Partial<Scope>): ReturnType<Array<Scope>["push"]>; | ||||||
|  | 	/** Adds root scope as a child of the current scope. */ | ||||||
|  | 	pushRoot(): ReturnType<Array<Scope>["push"]>; | ||||||
|  | 	/** Removes last/current child scope. */ | ||||||
|  | 	pop(): ReturnType<Array<Scope>["pop"]>; | ||||||
|  | }; | ||||||
|  | export function customElementRender<EL extends HTMLElement, P extends any = Record<string, string | Signal<string, {}>>>(target: ShadowRoot | EL, render: (props: P) => SupportedElement | DocumentFragment, props?: P | ((el: EL) => P)): EL; | ||||||
|  | export function customElementWithDDE<EL extends (new () => HTMLElement)>(custom_element: EL): EL; | ||||||
|  | export function lifecyclesToEvents<EL extends (new () => HTMLElement)>(custom_element: EL): EL; | ||||||
|  | /** | ||||||
|  |  * This is used primarly for server side rendering. To be sure that all async operations | ||||||
|  |  * are finished before the page is sent to the client. | ||||||
|  |  * ``` | ||||||
|  |  *	// on component | ||||||
|  |  *	function component(){ | ||||||
|  |  *		… | ||||||
|  |  *		queue(fetch(...).then(...)); | ||||||
|  |  *	} | ||||||
|  |  * | ||||||
|  |  * // building the page | ||||||
|  |  * async function build(){ | ||||||
|  |  *		const { component }= await import("./component.js"); | ||||||
|  |  *		document.body.append(el(component)); | ||||||
|  |  *		await queue(); | ||||||
|  |  *		retutn document.body.innerHTML; | ||||||
|  |  *	} | ||||||
|  |  * ``` | ||||||
|  |  * */ | ||||||
|  | export function queue(promise?: Promise<unknown>): Promise<unknown>; | ||||||
|  | /** | ||||||
|  |  * Memoization utility for caching DOM elements to improve performance. | ||||||
|  |  * Used to prevent unnecessary recreation of elements when rendering lists or complex components. | ||||||
|  |  * | ||||||
|  |  * @param key - Unique identifier for the element (usually an ID or unique value) | ||||||
|  |  * @param generator - Function that creates the element | ||||||
|  |  * @returns The cached element if the key exists, otherwise the result of the generator function | ||||||
|  |  * | ||||||
|  |  * @example | ||||||
|  |  * ```ts | ||||||
|  |  * // Within S.el for list rendering | ||||||
|  |  * S.el(itemsSignal, (items, memo) => | ||||||
|  |  *   el("ul").append( | ||||||
|  |  *     ...items.map(item => | ||||||
|  |  *       memo(item.id, () => el(ItemComponent, item)) | ||||||
|  |  *     ) | ||||||
|  |  *   ) | ||||||
|  |  * ) | ||||||
|  |  * ``` | ||||||
|  |  */ | ||||||
|  | export function memo<T>(key: string | number | object, generator: (key: any) => T): T; | ||||||
|  | /** | ||||||
|  |  * Memo namespace containing utility functions for memoization. | ||||||
|  |  */ | ||||||
|  | export namespace memo { | ||||||
|  | 	/** | ||||||
|  | 	 * Checks if an object is a memo scope. | ||||||
|  | 	 * @param obj - The object to check | ||||||
|  | 	 * @returns True if the object is a memo scope | ||||||
|  | 	 */ | ||||||
|  | 	export function isScope(obj: any): boolean; | ||||||
|  | 	/** | ||||||
|  | 	 * Creates a memoized function with optional cleanup support. | ||||||
|  | 	 * | ||||||
|  | 	 * @param fun - The function to memoize | ||||||
|  | 	 * @param options - Configuration options | ||||||
|  | 	 * @param options.signal - AbortSignal for cleanup | ||||||
|  | 	 * @param options.onlyLast - When true, only keeps the cache from the most recent call | ||||||
|  | 	 * @returns A memoized version of the function with a .clear() method | ||||||
|  | 	 * | ||||||
|  | 	 * @example | ||||||
|  | 	 * ```ts | ||||||
|  | 	 * const renderItems = memo.scope(function(items) { | ||||||
|  | 	 *	 return items.map(item => | ||||||
|  | 	 *		 memo(item.id, () => el("div", item.name)) | ||||||
|  | 	 *	 ); | ||||||
|  | 	 * }, { | ||||||
|  | 	 *	 signal: controller.signal, | ||||||
|  | 	 *	 onlyLast: true | ||||||
|  | 	 * }); | ||||||
|  | 	 * ``` | ||||||
|  | 	 */ | ||||||
|  | 	export function scope<F extends Function>(fun: F, options?: { | ||||||
|  | 		signal?: AbortSignal; | ||||||
|  | 		onlyLast?: boolean; | ||||||
|  | 	}): F & { | ||||||
|  | 		clear: () => void; | ||||||
|  | 	}; | ||||||
|  | } | ||||||
|  | /* TypeScript MEH */ | ||||||
|  | declare global { | ||||||
|  | 	type ddeAppend<el> = (...nodes: (Node | string)[]) => el; | ||||||
|  | 	interface ddeDocumentFragment extends DocumentFragment { | ||||||
|  | 		append: ddeAppend<ddeDocumentFragment>; | ||||||
|  | 	} | ||||||
|  | 	interface ddeHTMLElement extends HTMLElement { | ||||||
|  | 		append: ddeAppend<ddeHTMLElement>; | ||||||
|  | 	} | ||||||
|  | 	interface ddeSVGElement extends SVGElement { | ||||||
|  | 		append: ddeAppend<ddeSVGElement>; | ||||||
|  | 	} | ||||||
|  | 	interface ddeMathMLElement extends MathMLElement { | ||||||
|  | 		append: ddeAppend<ddeMathMLElement>; | ||||||
|  | 	} | ||||||
|  | 	interface ddeHTMLElementTagNameMap { | ||||||
|  | 		"a": ddeHTMLAnchorElement; | ||||||
|  | 		"area": ddeHTMLAreaElement; | ||||||
|  | 		"audio": ddeHTMLAudioElement; | ||||||
|  | 		"base": ddeHTMLBaseElement; | ||||||
|  | 		"blockquote": ddeHTMLQuoteElement; | ||||||
|  | 		"body": ddeHTMLBodyElement; | ||||||
|  | 		"br": ddeHTMLBRElement; | ||||||
|  | 		"button": ddeHTMLButtonElement; | ||||||
|  | 		"canvas": ddeHTMLCanvasElement; | ||||||
|  | 		"caption": ddeHTMLTableCaptionElement; | ||||||
|  | 		"col": ddeHTMLTableColElement; | ||||||
|  | 		"colgroup": ddeHTMLTableColElement; | ||||||
|  | 		"data": ddeHTMLDataElement; | ||||||
|  | 		"datalist": ddeHTMLDataListElement; | ||||||
|  | 		"del": ddeHTMLModElement; | ||||||
|  | 		"details": ddeHTMLDetailsElement; | ||||||
|  | 		"dialog": ddeHTMLDialogElement; | ||||||
|  | 		"div": ddeHTMLDivElement; | ||||||
|  | 		"dl": ddeHTMLDListElement; | ||||||
|  | 		"embed": ddeHTMLEmbedElement; | ||||||
|  | 		"fieldset": ddeHTMLFieldSetElement; | ||||||
|  | 		"form": ddeHTMLFormElement; | ||||||
|  | 		"h1": ddeHTMLHeadingElement; | ||||||
|  | 		"h2": ddeHTMLHeadingElement; | ||||||
|  | 		"h3": ddeHTMLHeadingElement; | ||||||
|  | 		"h4": ddeHTMLHeadingElement; | ||||||
|  | 		"h5": ddeHTMLHeadingElement; | ||||||
|  | 		"h6": ddeHTMLHeadingElement; | ||||||
|  | 		"head": ddeHTMLHeadElement; | ||||||
|  | 		"hr": ddeHTMLHRElement; | ||||||
|  | 		"html": ddeHTMLHtmlElement; | ||||||
|  | 		"iframe": ddeHTMLIFrameElement; | ||||||
|  | 		"img": ddeHTMLImageElement; | ||||||
|  | 		"input": ddeHTMLInputElement; | ||||||
|  | 		"ins": ddeHTMLModElement; | ||||||
|  | 		"label": ddeHTMLLabelElement; | ||||||
|  | 		"legend": ddeHTMLLegendElement; | ||||||
|  | 		"li": ddeHTMLLIElement; | ||||||
|  | 		"link": ddeHTMLLinkElement; | ||||||
|  | 		"map": ddeHTMLMapElement; | ||||||
|  | 		"menu": ddeHTMLMenuElement; | ||||||
|  | 		"meta": ddeHTMLMetaElement; | ||||||
|  | 		"meter": ddeHTMLMeterElement; | ||||||
|  | 		"object": ddeHTMLObjectElement; | ||||||
|  | 		"ol": ddeHTMLOListElement; | ||||||
|  | 		"optgroup": ddeHTMLOptGroupElement; | ||||||
|  | 		"option": ddeHTMLOptionElement; | ||||||
|  | 		"output": ddeHTMLOutputElement; | ||||||
|  | 		"p": ddeHTMLParagraphElement; | ||||||
|  | 		"picture": ddeHTMLPictureElement; | ||||||
|  | 		"pre": ddeHTMLPreElement; | ||||||
|  | 		"progress": ddeHTMLProgressElement; | ||||||
|  | 		"q": ddeHTMLQuoteElement; | ||||||
|  | 		"script": ddeHTMLScriptElement; | ||||||
|  | 		"select": ddeHTMLSelectElement; | ||||||
|  | 		"slot": ddeHTMLSlotElement; | ||||||
|  | 		"source": ddeHTMLSourceElement; | ||||||
|  | 		"span": ddeHTMLSpanElement; | ||||||
|  | 		"style": ddeHTMLStyleElement; | ||||||
|  | 		"table": ddeHTMLTableElement; | ||||||
|  | 		"tbody": ddeHTMLTableSectionElement; | ||||||
|  | 		"td": ddeHTMLTableCellElement; | ||||||
|  | 		"template": ddeHTMLTemplateElement; | ||||||
|  | 		"textarea": ddeHTMLTextAreaElement; | ||||||
|  | 		"tfoot": ddeHTMLTableSectionElement; | ||||||
|  | 		"th": ddeHTMLTableCellElement; | ||||||
|  | 		"thead": ddeHTMLTableSectionElement; | ||||||
|  | 		"time": ddeHTMLTimeElement; | ||||||
|  | 		"title": ddeHTMLTitleElement; | ||||||
|  | 		"tr": ddeHTMLTableRowElement; | ||||||
|  | 		"track": ddeHTMLTrackElement; | ||||||
|  | 		"ul": ddeHTMLUListElement; | ||||||
|  | 		"video": ddeHTMLVideoElement; | ||||||
|  | 	} | ||||||
|  | 	interface ddeSVGElementTagNameMap { | ||||||
|  | 		"a": ddeSVGAElement; | ||||||
|  | 		"animate": ddeSVGAnimateElement; | ||||||
|  | 		"animateMotion": ddeSVGAnimateMotionElement; | ||||||
|  | 		"animateTransform": ddeSVGAnimateTransformElement; | ||||||
|  | 		"circle": ddeSVGCircleElement; | ||||||
|  | 		"clipPath": ddeSVGClipPathElement; | ||||||
|  | 		"defs": ddeSVGDefsElement; | ||||||
|  | 		"desc": ddeSVGDescElement; | ||||||
|  | 		"ellipse": ddeSVGEllipseElement; | ||||||
|  | 		"feBlend": ddeSVGFEBlendElement; | ||||||
|  | 		"feColorMatrix": ddeSVGFEColorMatrixElement; | ||||||
|  | 		"feComponentTransfer": ddeSVGFEComponentTransferElement; | ||||||
|  | 		"feComposite": ddeSVGFECompositeElement; | ||||||
|  | 		"feConvolveMatrix": ddeSVGFEConvolveMatrixElement; | ||||||
|  | 		"feDiffuseLighting": ddeSVGFEDiffuseLightingElement; | ||||||
|  | 		"feDisplacementMap": ddeSVGFEDisplacementMapElement; | ||||||
|  | 		"feDistantLight": ddeSVGFEDistantLightElement; | ||||||
|  | 		"feDropShadow": ddeSVGFEDropShadowElement; | ||||||
|  | 		"feFlood": ddeSVGFEFloodElement; | ||||||
|  | 		"feFuncA": ddeSVGFEFuncAElement; | ||||||
|  | 		"feFuncB": ddeSVGFEFuncBElement; | ||||||
|  | 		"feFuncG": ddeSVGFEFuncGElement; | ||||||
|  | 		"feFuncR": ddeSVGFEFuncRElement; | ||||||
|  | 		"feGaussianBlur": ddeSVGFEGaussianBlurElement; | ||||||
|  | 		"feImage": ddeSVGFEImageElement; | ||||||
|  | 		"feMerge": ddeSVGFEMergeElement; | ||||||
|  | 		"feMergeNode": ddeSVGFEMergeNodeElement; | ||||||
|  | 		"feMorphology": ddeSVGFEMorphologyElement; | ||||||
|  | 		"feOffset": ddeSVGFEOffsetElement; | ||||||
|  | 		"fePointLight": ddeSVGFEPointLightElement; | ||||||
|  | 		"feSpecularLighting": ddeSVGFESpecularLightingElement; | ||||||
|  | 		"feSpotLight": ddeSVGFESpotLightElement; | ||||||
|  | 		"feTile": ddeSVGFETileElement; | ||||||
|  | 		"feTurbulence": ddeSVGFETurbulenceElement; | ||||||
|  | 		"filter": ddeSVGFilterElement; | ||||||
|  | 		"foreignObject": ddeSVGForeignObjectElement; | ||||||
|  | 		"g": ddeSVGGElement; | ||||||
|  | 		"image": ddeSVGImageElement; | ||||||
|  | 		"line": ddeSVGLineElement; | ||||||
|  | 		"linearGradient": ddeSVGLinearGradientElement; | ||||||
|  | 		"marker": ddeSVGMarkerElement; | ||||||
|  | 		"mask": ddeSVGMaskElement; | ||||||
|  | 		"metadata": ddeSVGMetadataElement; | ||||||
|  | 		"mpath": ddeSVGMPathElement; | ||||||
|  | 		"path": ddeSVGPathElement; | ||||||
|  | 		"pattern": ddeSVGPatternElement; | ||||||
|  | 		"polygon": ddeSVGPolygonElement; | ||||||
|  | 		"polyline": ddeSVGPolylineElement; | ||||||
|  | 		"radialGradient": ddeSVGRadialGradientElement; | ||||||
|  | 		"rect": ddeSVGRectElement; | ||||||
|  | 		"script": ddeSVGScriptElement; | ||||||
|  | 		"set": ddeSVGSetElement; | ||||||
|  | 		"stop": ddeSVGStopElement; | ||||||
|  | 		"style": ddeSVGStyleElement; | ||||||
|  | 		"svg": ddeSVGSVGElement; | ||||||
|  | 		"switch": ddeSVGSwitchElement; | ||||||
|  | 		"symbol": ddeSVGSymbolElement; | ||||||
|  | 		"text": ddeSVGTextElement; | ||||||
|  | 		"textPath": ddeSVGTextPathElement; | ||||||
|  | 		"title": ddeSVGTitleElement; | ||||||
|  | 		"tspan": ddeSVGTSpanElement; | ||||||
|  | 		"use": ddeSVGUseElement; | ||||||
|  | 		"view": ddeSVGViewElement; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | // editorconfig-checker-disable | ||||||
|  | export interface ddeHTMLAnchorElement extends HTMLAnchorElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLAnchorElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLAreaElement extends HTMLAreaElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLAreaElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLAudioElement extends HTMLAudioElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLAudioElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLBaseElement extends HTMLBaseElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLBaseElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLQuoteElement extends HTMLQuoteElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLQuoteElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLBodyElement extends HTMLBodyElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLBodyElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLBRElement extends HTMLBRElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLBRElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLButtonElement extends HTMLButtonElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLButtonElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLCanvasElement extends HTMLCanvasElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLCanvasElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLTableCaptionElement extends HTMLTableCaptionElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLTableCaptionElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLTableColElement extends HTMLTableColElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLTableColElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLTableColElement extends HTMLTableColElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLTableColElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLDataElement extends HTMLDataElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLDataElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLDataListElement extends HTMLDataListElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLDataListElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLModElement extends HTMLModElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLModElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLDetailsElement extends HTMLDetailsElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLDetailsElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLDialogElement extends HTMLDialogElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLDialogElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLDivElement extends HTMLDivElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLDivElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLDListElement extends HTMLDListElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLDListElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLEmbedElement extends HTMLEmbedElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLEmbedElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLFieldSetElement extends HTMLFieldSetElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLFieldSetElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLFormElement extends HTMLFormElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLFormElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLHeadingElement extends HTMLHeadingElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLHeadingElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLHeadElement extends HTMLHeadElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLHeadElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLHRElement extends HTMLHRElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLHRElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLHtmlElement extends HTMLHtmlElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLHtmlElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLIFrameElement extends HTMLIFrameElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLIFrameElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLImageElement extends HTMLImageElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLImageElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLInputElement extends HTMLInputElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLInputElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLLabelElement extends HTMLLabelElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLLabelElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLLegendElement extends HTMLLegendElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLLegendElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLLIElement extends HTMLLIElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLLIElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLLinkElement extends HTMLLinkElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLLinkElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLMapElement extends HTMLMapElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLMapElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLMenuElement extends HTMLMenuElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLMenuElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLMetaElement extends HTMLMetaElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLMetaElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLMeterElement extends HTMLMeterElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLMeterElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLObjectElement extends HTMLObjectElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLObjectElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLOListElement extends HTMLOListElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLOListElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLOptGroupElement extends HTMLOptGroupElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLOptGroupElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLOptionElement extends HTMLOptionElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLOptionElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLOutputElement extends HTMLOutputElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLOutputElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLParagraphElement extends HTMLParagraphElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLParagraphElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLPictureElement extends HTMLPictureElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLPictureElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLPreElement extends HTMLPreElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLPreElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLProgressElement extends HTMLProgressElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLProgressElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLScriptElement extends HTMLScriptElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLScriptElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLSelectElement extends HTMLSelectElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLSelectElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLSlotElement extends HTMLSlotElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLSlotElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLSourceElement extends HTMLSourceElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLSourceElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLSpanElement extends HTMLSpanElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLSpanElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLStyleElement extends HTMLStyleElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLStyleElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLTableElement extends HTMLTableElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLTableElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLTableSectionElement extends HTMLTableSectionElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLTableSectionElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLTableCellElement extends HTMLTableCellElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLTableCellElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLTemplateElement extends HTMLTemplateElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLTemplateElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLTextAreaElement extends HTMLTextAreaElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLTextAreaElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLTableCellElement extends HTMLTableCellElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLTableCellElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLTimeElement extends HTMLTimeElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLTimeElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLTitleElement extends HTMLTitleElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLTitleElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLTableRowElement extends HTMLTableRowElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLTableRowElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLTrackElement extends HTMLTrackElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLTrackElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLUListElement extends HTMLUListElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLUListElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLVideoElement extends HTMLVideoElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLVideoElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGAElement extends SVGAElement { | ||||||
|  | 	append: ddeAppend<ddeSVGAElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGAnimateElement extends SVGAnimateElement { | ||||||
|  | 	append: ddeAppend<ddeSVGAnimateElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGAnimateMotionElement extends SVGAnimateMotionElement { | ||||||
|  | 	append: ddeAppend<ddeSVGAnimateMotionElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGAnimateTransformElement extends SVGAnimateTransformElement { | ||||||
|  | 	append: ddeAppend<ddeSVGAnimateTransformElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGCircleElement extends SVGCircleElement { | ||||||
|  | 	append: ddeAppend<ddeSVGCircleElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGClipPathElement extends SVGClipPathElement { | ||||||
|  | 	append: ddeAppend<ddeSVGClipPathElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGDefsElement extends SVGDefsElement { | ||||||
|  | 	append: ddeAppend<ddeSVGDefsElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGDescElement extends SVGDescElement { | ||||||
|  | 	append: ddeAppend<ddeSVGDescElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGEllipseElement extends SVGEllipseElement { | ||||||
|  | 	append: ddeAppend<ddeSVGEllipseElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEBlendElement extends SVGFEBlendElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEBlendElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEColorMatrixElement extends SVGFEColorMatrixElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEColorMatrixElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEComponentTransferElement extends SVGFEComponentTransferElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEComponentTransferElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFECompositeElement extends SVGFECompositeElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFECompositeElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEConvolveMatrixElement extends SVGFEConvolveMatrixElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEConvolveMatrixElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEDiffuseLightingElement extends SVGFEDiffuseLightingElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEDiffuseLightingElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEDisplacementMapElement extends SVGFEDisplacementMapElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEDisplacementMapElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEDistantLightElement extends SVGFEDistantLightElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEDistantLightElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEDropShadowElement extends SVGFEDropShadowElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEDropShadowElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEFloodElement extends SVGFEFloodElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEFloodElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEFuncAElement extends SVGFEFuncAElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEFuncAElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEFuncBElement extends SVGFEFuncBElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEFuncBElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEFuncGElement extends SVGFEFuncGElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEFuncGElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEFuncRElement extends SVGFEFuncRElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEFuncRElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEGaussianBlurElement extends SVGFEGaussianBlurElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEGaussianBlurElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEImageElement extends SVGFEImageElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEImageElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEMergeElement extends SVGFEMergeElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEMergeElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEMergeNodeElement extends SVGFEMergeNodeElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEMergeNodeElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEMorphologyElement extends SVGFEMorphologyElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEMorphologyElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEOffsetElement extends SVGFEOffsetElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEOffsetElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEPointLightElement extends SVGFEPointLightElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEPointLightElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFESpecularLightingElement extends SVGFESpecularLightingElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFESpecularLightingElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFESpotLightElement extends SVGFESpotLightElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFESpotLightElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFETileElement extends SVGFETileElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFETileElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFETurbulenceElement extends SVGFETurbulenceElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFETurbulenceElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFilterElement extends SVGFilterElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFilterElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGForeignObjectElement extends SVGForeignObjectElement { | ||||||
|  | 	append: ddeAppend<ddeSVGForeignObjectElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGGElement extends SVGGElement { | ||||||
|  | 	append: ddeAppend<ddeSVGGElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGImageElement extends SVGImageElement { | ||||||
|  | 	append: ddeAppend<ddeSVGImageElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGLineElement extends SVGLineElement { | ||||||
|  | 	append: ddeAppend<ddeSVGLineElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGLinearGradientElement extends SVGLinearGradientElement { | ||||||
|  | 	append: ddeAppend<ddeSVGLinearGradientElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGMarkerElement extends SVGMarkerElement { | ||||||
|  | 	append: ddeAppend<ddeSVGMarkerElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGMaskElement extends SVGMaskElement { | ||||||
|  | 	append: ddeAppend<ddeSVGMaskElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGMetadataElement extends SVGMetadataElement { | ||||||
|  | 	append: ddeAppend<ddeSVGMetadataElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGMPathElement extends SVGMPathElement { | ||||||
|  | 	append: ddeAppend<ddeSVGMPathElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGPathElement extends SVGPathElement { | ||||||
|  | 	append: ddeAppend<ddeSVGPathElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGPatternElement extends SVGPatternElement { | ||||||
|  | 	append: ddeAppend<ddeSVGPatternElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGPolygonElement extends SVGPolygonElement { | ||||||
|  | 	append: ddeAppend<ddeSVGPolygonElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGPolylineElement extends SVGPolylineElement { | ||||||
|  | 	append: ddeAppend<ddeSVGPolylineElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGRadialGradientElement extends SVGRadialGradientElement { | ||||||
|  | 	append: ddeAppend<ddeSVGRadialGradientElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGRectElement extends SVGRectElement { | ||||||
|  | 	append: ddeAppend<ddeSVGRectElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGScriptElement extends SVGScriptElement { | ||||||
|  | 	append: ddeAppend<ddeSVGScriptElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGSetElement extends SVGSetElement { | ||||||
|  | 	append: ddeAppend<ddeSVGSetElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGStopElement extends SVGStopElement { | ||||||
|  | 	append: ddeAppend<ddeSVGStopElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGStyleElement extends SVGStyleElement { | ||||||
|  | 	append: ddeAppend<ddeSVGStyleElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGSVGElement extends SVGSVGElement { | ||||||
|  | 	append: ddeAppend<ddeSVGSVGElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGSwitchElement extends SVGSwitchElement { | ||||||
|  | 	append: ddeAppend<ddeSVGSwitchElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGSymbolElement extends SVGSymbolElement { | ||||||
|  | 	append: ddeAppend<ddeSVGSymbolElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGTextElement extends SVGTextElement { | ||||||
|  | 	append: ddeAppend<ddeSVGTextElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGTextPathElement extends SVGTextPathElement { | ||||||
|  | 	append: ddeAppend<ddeSVGTextPathElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGTitleElement extends SVGTitleElement { | ||||||
|  | 	append: ddeAppend<ddeSVGTitleElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGTSpanElement extends SVGTSpanElement { | ||||||
|  | 	append: ddeAppend<ddeSVGTSpanElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGUseElement extends SVGUseElement { | ||||||
|  | 	append: ddeAppend<ddeSVGUseElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGViewElement extends SVGViewElement { | ||||||
|  | 	append: ddeAppend<ddeSVGViewElement>; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | export { | ||||||
|  | 	dispatchEvent$1 as dispatchEvent, | ||||||
|  | 	el as createElement, | ||||||
|  | 	elNS as createElementNS, | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | export {}; | ||||||
							
								
								
									
										1
									
								
								dist/esm.min.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								dist/esm.min.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										862
									
								
								dist/iife-with-signals.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										862
									
								
								dist/iife-with-signals.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,862 @@ | |||||||
|  | // Generated by dts-bundle-generator v9.5.1 | ||||||
|  |  | ||||||
|  | export interface Signal<V, A> { | ||||||
|  | 	/** The current value of the signal */ | ||||||
|  | 	get(): V; | ||||||
|  | 	/** Set new value of the signal */ | ||||||
|  | 	set(value: V, force?: boolean): V; | ||||||
|  | 	toJSON(): V; | ||||||
|  | 	valueOf(): V; | ||||||
|  | } | ||||||
|  | export type Action<V> = (this: { | ||||||
|  | 	value: V; | ||||||
|  | 	stopPropagation(): void; | ||||||
|  | }, ...a: any[]) => typeof signal._ | void; | ||||||
|  | //type SymbolSignal= Symbol; | ||||||
|  | export type SymbolOnclear = symbol; | ||||||
|  | export type Actions<V> = Record<string | SymbolOnclear, Action<V>>; | ||||||
|  | export type OnListenerOptions = Pick<AddEventListenerOptions, "signal"> & { | ||||||
|  | 	first_time?: boolean; | ||||||
|  | }; | ||||||
|  | export type SElement = Node | Element | DocumentFragment | ddeHTMLElement | ddeSVGElement | ddeDocumentFragment; | ||||||
|  | export interface signal { | ||||||
|  | 	_: Symbol; | ||||||
|  | 	/** | ||||||
|  | 	 * Computations signal. This creates a signal which is computed from other signals. | ||||||
|  | 	 * */ | ||||||
|  | 	<V extends () => any>(computation: V): Signal<ReturnType<V>, {}>; | ||||||
|  | 	/** | ||||||
|  | 	 * Simple example: | ||||||
|  | 	 * ```js | ||||||
|  | 	 * const hello= S("Hello Signal"); | ||||||
|  | 	 * ``` | ||||||
|  | 	 * …simple todo signal: | ||||||
|  | 	 * ```js | ||||||
|  | 	 * const todos= S([], { | ||||||
|  | 	 * 	add(v){ this.value.push(S(v)); }, | ||||||
|  | 	 * 	remove(i){ this.value.splice(i, 1); }, | ||||||
|  | 	 * 	[S.symbols.onclear](){ S.clear(...this.value); }, | ||||||
|  | 	 * }); | ||||||
|  | 	 * ``` | ||||||
|  | 	 * …computed signal: | ||||||
|  | 	 * ```js | ||||||
|  | 	 * const name= S("Jan"); | ||||||
|  | 	 * const surname= S("Andrle"); | ||||||
|  | 	 * const fullname= S(()=> name.get()+" "+surname.get()); | ||||||
|  | 	 * ``` | ||||||
|  | 	 * @param value Initial signal value. Or function computing value from other signals. | ||||||
|  | 	 * @param actions Use to define actions on the signal. Such as add item to the array. | ||||||
|  | 	 *		There is also a reserved function `S.symbol.onclear` which is called when the signal is cleared | ||||||
|  | 	 *		by `S.clear`. | ||||||
|  | 	 * */ | ||||||
|  | 	<V, A extends Actions<V>>(value: V, actions?: A): Signal<V, A>; | ||||||
|  | 	action<S extends Signal<any, Actions<any>>, A extends (S extends Signal<any, infer A> ? A : never), N extends keyof A>(signal: S, name: N, ...params: A[N] extends (...args: infer P) => any ? P : never): void; | ||||||
|  | 	clear(...signals: Signal<any, any>[]): void; | ||||||
|  | 	on<T>(signal: Signal<T, any>, onchange: (a: T) => void, options?: OnListenerOptions): void; | ||||||
|  | 	symbols: { | ||||||
|  | 		//signal: SymbolSignal; | ||||||
|  | 		onclear: SymbolOnclear; | ||||||
|  | 	}; | ||||||
|  | 	/** | ||||||
|  | 	 * Reactive element, which is rendered based on the given signal. | ||||||
|  | 	 * ```js | ||||||
|  | 	 * S.el(signal, value=> value ? el("b", "True") : el("i", "False")); | ||||||
|  | 	 * S.el(listS, list=> list.map(li=> el("li", li))); | ||||||
|  | 	 * ``` | ||||||
|  | 	 * */ | ||||||
|  | 	el<S extends any>(signal: Signal<S, any>, el: (v: S) => SElement | SElement[]): DocumentFragment; | ||||||
|  | 	observedAttributes(custom_element: HTMLElement): Record<string, Signal<string, {}>>; | ||||||
|  | } | ||||||
|  | export const signal: signal; | ||||||
|  | export const S: signal; | ||||||
|  | declare global { | ||||||
|  | 	type ddeSignal<T, A = {}> = Signal<T, A>; | ||||||
|  | 	type ddeAction<V> = Action<V>; | ||||||
|  | 	type ddeActions<V> = Actions<V>; | ||||||
|  | } | ||||||
|  | export type CustomElementTagNameMap = { | ||||||
|  | 	"#text": Text; | ||||||
|  | 	"#comment": Comment; | ||||||
|  | }; | ||||||
|  | export type SupportedElement = HTMLElementTagNameMap[keyof HTMLElementTagNameMap] | SVGElementTagNameMap[keyof SVGElementTagNameMap] | MathMLElementTagNameMap[keyof MathMLElementTagNameMap] | CustomElementTagNameMap[keyof CustomElementTagNameMap]; | ||||||
|  | declare global { | ||||||
|  | 	type ddeComponentAttributes = Record<any, any> | undefined; | ||||||
|  | 	type ddeElementAddon<El extends SupportedElement | DocumentFragment | Node> = (element: El, ...rest: any) => any; | ||||||
|  | 	type ddeString = string | Signal<string, {}>; | ||||||
|  | 	type ddeStringable = ddeString | number | Signal<number, {}>; | ||||||
|  | } | ||||||
|  | export type Host<EL extends SupportedElement> = (...addons: ddeElementAddon<EL>[]) => EL; | ||||||
|  | export type PascalCase = `${Capitalize<string>}${string}`; | ||||||
|  | export type AttrsModified = { | ||||||
|  | 	/** | ||||||
|  | 	 * Use string like in HTML (internally uses `*.setAttribute("style", *)`), or object representation (like DOM API). | ||||||
|  | 	 */ | ||||||
|  | 	style: Partial<CSSStyleDeclaration> | ddeString | Partial<{ | ||||||
|  | 		[K in keyof CSSStyleDeclaration]: Signal<CSSStyleDeclaration[K], {}>; | ||||||
|  | 	}>; | ||||||
|  | 	/** | ||||||
|  | 	 * Provide option to add/remove/toggle CSS clasess (index of object) using 1/0/-1. | ||||||
|  | 	 * In fact `el.classList.toggle(class_name)` for `-1` and `el.classList.toggle(class_name, Boolean(...))` | ||||||
|  | 	 * for others. | ||||||
|  | 	 */ | ||||||
|  | 	classList: Record<string, -1 | 0 | 1 | boolean | Signal<-1 | 0 | 1 | boolean, {}>>; | ||||||
|  | 	/** | ||||||
|  | 	 * Used by the dataset HTML attribute to represent data for custom attributes added to elements. | ||||||
|  | 	 * Values are converted to string (see {@link DOMStringMap}). | ||||||
|  | 	 * | ||||||
|  | 	 * [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMStringMap) | ||||||
|  | 	 * */ | ||||||
|  | 	dataset: Record<string, ddeStringable>; | ||||||
|  | 	/** | ||||||
|  | 	 * Sets `aria-*` simiraly to `dataset` | ||||||
|  | 	 * */ | ||||||
|  | 	ariaset: Record<string, ddeString>; | ||||||
|  | } & Record<`=${string}` | `data${PascalCase}` | `aria${PascalCase}`, ddeString> & Record<`.${string}`, any>; | ||||||
|  | export type _fromElsInterfaces<EL extends SupportedElement> = Omit<EL, keyof AttrsModified>; | ||||||
|  | export type IsReadonly<T, K extends keyof T> = T extends { | ||||||
|  | 	readonly [P in K]: T[K]; | ||||||
|  | } ? true : false; | ||||||
|  | /** | ||||||
|  |  * Just element attributtes | ||||||
|  |  * | ||||||
|  |  * In most cases, you can use native propertie such as | ||||||
|  |  * [MDN WEB/API/Element](https://developer.mozilla.org/en-US/docs/Web/API/Element) and so on | ||||||
|  |  * (e.g. [`Text`](https://developer.mozilla.org/en-US/docs/Web/API/Text)). | ||||||
|  |  * | ||||||
|  |  * There is added support for `data[A-Z].*`/`aria[A-Z].*` to be converted to the kebab-case alternatives. | ||||||
|  |  * @private | ||||||
|  |  */ | ||||||
|  | export type ElementAttributes<T extends SupportedElement> = Partial<{ | ||||||
|  | 	[K in keyof _fromElsInterfaces<T>]: _fromElsInterfaces<T>[K] extends ((...p: any[]) => any) ? _fromElsInterfaces<T>[K] | ((...p: Parameters<_fromElsInterfaces<T>[K]>) => Signal<ReturnType<_fromElsInterfaces<T>[K]>, {}>) : (IsReadonly<_fromElsInterfaces<T>, K> extends false ? _fromElsInterfaces<T>[K] | Signal<_fromElsInterfaces<T>[K], {}> : ddeStringable); | ||||||
|  | } & AttrsModified> & Record<string, any>; | ||||||
|  | export function classListDeclarative<El extends SupportedElement>(element: El, classList: AttrsModified["classList"]): El; | ||||||
|  | export function assign<El extends SupportedElement>(element: El, ...attrs_array: ElementAttributes<El>[]): El; | ||||||
|  | export function assignAttribute<El extends SupportedElement, ATT extends keyof ElementAttributes<El>>(element: El, attr: ATT, value: ElementAttributes<El>[ATT]): ElementAttributes<El>[ATT]; | ||||||
|  | export type ExtendedHTMLElementTagNameMap = HTMLElementTagNameMap & CustomElementTagNameMap; | ||||||
|  | export namespace el { | ||||||
|  | 	/** | ||||||
|  | 	 * Creates a marker comment for elements | ||||||
|  | 	 * | ||||||
|  | 	 * @param attrs - Marker attributes | ||||||
|  | 	 * @param [is_open=false] - Whether the marker is open-ended | ||||||
|  | 	 * @returns Comment node marker | ||||||
|  | 	 */ | ||||||
|  | 	export function mark(attrs: { | ||||||
|  | 		type: "component" | "reactive" | "later"; | ||||||
|  | 		name?: string; | ||||||
|  | 		host?: "this" | "parentElement"; | ||||||
|  | 	}, is_open?: boolean): Comment; | ||||||
|  | } | ||||||
|  | export function chainableAppend<EL extends SupportedElement>(el: EL): EL | ddeHTMLElement; | ||||||
|  | export function el<A extends ddeComponentAttributes, EL extends SupportedElement | ddeDocumentFragment>(component: (attr: A, ...rest: any[]) => EL, attrs?: NoInfer<A>, ...addons: ddeElementAddon<EL>[]): EL extends ddeHTMLElementTagNameMap[keyof ddeHTMLElementTagNameMap] ? EL : (EL extends ddeDocumentFragment ? EL : ddeHTMLElement); | ||||||
|  | export function el<A extends { | ||||||
|  | 	textContent: ddeStringable; | ||||||
|  | }, EL extends SupportedElement | ddeDocumentFragment>(component: (attr: A, ...rest: any[]) => EL, attrs?: NoInfer<A>["textContent"], ...addons: ddeElementAddon<EL>[]): EL extends ddeHTMLElementTagNameMap[keyof ddeHTMLElementTagNameMap] ? EL : (EL extends ddeDocumentFragment ? EL : ddeHTMLElement); | ||||||
|  | export function el<TAG extends keyof ExtendedHTMLElementTagNameMap>(tag_name: TAG, attrs?: ElementAttributes<ExtendedHTMLElementTagNameMap[NoInfer<TAG>]> | ddeStringable, ...addons: ddeElementAddon<ExtendedHTMLElementTagNameMap[NoInfer<TAG>]>[]): TAG extends keyof ddeHTMLElementTagNameMap ? ddeHTMLElementTagNameMap[TAG] : ddeHTMLElement; | ||||||
|  | export function el(tag_name?: "<>"): ddeDocumentFragment; | ||||||
|  | export function el(tag_name: string, attrs?: ElementAttributes<HTMLElement> | ddeStringable, ...addons: ddeElementAddon<HTMLElement>[]): ddeHTMLElement; | ||||||
|  | export function elNS(namespace: "http://www.w3.org/2000/svg"): <TAG extends keyof SVGElementTagNameMap & string, EL extends (TAG extends keyof SVGElementTagNameMap ? SVGElementTagNameMap[TAG] : SVGElement)>(tag_name: TAG, attrs?: ElementAttributes<NoInfer<EL>> | ddeStringable, ...addons: ddeElementAddon<NoInfer<EL>>[]) => TAG extends keyof ddeSVGElementTagNameMap ? ddeSVGElementTagNameMap[TAG] : ddeSVGElement; | ||||||
|  | export function elNS(namespace: "http://www.w3.org/1998/Math/MathML"): <TAG extends keyof MathMLElementTagNameMap & string, EL extends (TAG extends keyof MathMLElementTagNameMap ? MathMLElementTagNameMap[TAG] : MathMLElement)>(tag_name: TAG, attrs?: ddeStringable | Partial<{ | ||||||
|  | 	[key in keyof EL]: EL[key] | Signal<EL[key], {}> | string | number | boolean; | ||||||
|  | }>, ...addons: ddeElementAddon<NoInfer<EL>>[]) => ddeMathMLElement; | ||||||
|  | export function elNS(namespace: string): (tag_name: string, attrs?: string | ddeStringable | Record<string, any>, ...addons: ddeElementAddon<SupportedElement>[]) => SupportedElement; | ||||||
|  | /** Simulate slots for ddeComponents */ | ||||||
|  | export function simulateSlots<EL extends SupportedElement | DocumentFragment>(root: EL): EL; | ||||||
|  | /** | ||||||
|  |  * Simulate slots in Custom Elements without using `shadowRoot`. | ||||||
|  |  * @param el Custom Element root element | ||||||
|  |  * @param body Body of the custom element | ||||||
|  |  * */ | ||||||
|  | export function simulateSlots<EL extends SupportedElement | DocumentFragment>(el: HTMLElement, body: EL): EL; | ||||||
|  | declare function dispatchEvent$1(name: keyof DocumentEventMap | string, host: Host<SupportedElement>): (data?: any) => void; | ||||||
|  | declare function dispatchEvent$1(name: keyof DocumentEventMap | string, options?: EventInit): (element: SupportedElement, data?: any) => void; | ||||||
|  | declare function dispatchEvent$1(name: keyof DocumentEventMap | string, options: EventInit | null, host: Host<SupportedElement>): (data?: any) => void; | ||||||
|  | export interface On { | ||||||
|  | 	/** Listens to the DOM event. See {@link Document.addEventListener} */ | ||||||
|  | 	<Event extends keyof DocumentEventMap, EL extends SupportedElement>(type: Event, listener: (this: EL, ev: DocumentEventMap[Event] & { | ||||||
|  | 		target: EL; | ||||||
|  | 	}) => any, options?: AddEventListenerOptions): ddeElementAddon<EL>; | ||||||
|  | 	<EE extends ddeElementAddon<SupportedElement> = ddeElementAddon<HTMLElement>>(type: string, listener: (this: EE extends ddeElementAddon<infer El> ? El : never, ev: Event | CustomEvent) => any, options?: AddEventListenerOptions): EE; | ||||||
|  | 	/** Listens to the element is connected to the live DOM. In case of custom elements uses [`connectedCallback`](https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_custom_elements#custom_element_lifecycle_callbacks), or {@link MutationObserver} else where */ // editorconfig-checker-disable-line | ||||||
|  | 	connected<EL extends SupportedElement>(listener: (this: EL, event: CustomEvent<NoInfer<EL>>) => any, options?: AddEventListenerOptions): ddeElementAddon<EL>; | ||||||
|  | 	/** Listens to the element is disconnected from the live DOM. In case of custom elements uses [`disconnectedCallback`](https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_custom_elements#custom_element_lifecycle_callbacks), or {@link MutationObserver} else where */ // editorconfig-checker-disable-line | ||||||
|  | 	disconnected<EL extends SupportedElement>(listener: (this: EL, event: CustomEvent<void>) => any, options?: AddEventListenerOptions): ddeElementAddon<EL>; | ||||||
|  | 	/** | ||||||
|  | 	 * Fires after the next tick of the Javascript event loop. | ||||||
|  | 	 * This is handy for example to apply some property depending on the element content: | ||||||
|  | 	 * ```js | ||||||
|  | 	 * const selected= "Z"; | ||||||
|  | 	 * //... | ||||||
|  | 	 * return el("form").append( | ||||||
|  | 	 *		el("select", null, on.defer(e=> e.value=selected)).append( | ||||||
|  | 	 *			el("option", { value: "A", textContent: "A" }), | ||||||
|  | 	 *			//... | ||||||
|  | 	 *			el("option", { value: "Z", textContent: "Z" }), | ||||||
|  | 	 *		), | ||||||
|  | 	 * ); | ||||||
|  | 	 * ``` | ||||||
|  | 	 * */ | ||||||
|  | 	defer<EL extends SupportedElement>(listener: (element: EL) => any): ddeElementAddon<EL>; | ||||||
|  | } | ||||||
|  | export const on: On; | ||||||
|  | export type Scope = { | ||||||
|  | 	scope: Node | Function | Object; | ||||||
|  | 	host: Host<SupportedElement>; | ||||||
|  | 	custom_element: false | HTMLElement; | ||||||
|  | 	prevent: boolean; | ||||||
|  | }; | ||||||
|  | /** Current scope created last time the `el(Function)` was invoke. (Or {@link scope.push}) */ | ||||||
|  | export const scope: { | ||||||
|  | 	current: Scope; | ||||||
|  | 	/** Stops all automatizations. E. g. signals used as attributes in current scope | ||||||
|  | 	 * registers removing these listeners (and clean signal if no other listeners are detected) | ||||||
|  | 	 * on `disconnected` event. */ | ||||||
|  | 	preventDefault<T extends boolean>(prevent: T): T; | ||||||
|  | 	/** | ||||||
|  | 	 * This represents reference to the current host element — `scope.host()`. | ||||||
|  | 	 * It can be also used to register Addon(s) (functions to be called when component is initized) | ||||||
|  | 	 * — `scope.host(on.connected(console.log))`. | ||||||
|  | 	 * */ | ||||||
|  | 	host: Host<SupportedElement>; | ||||||
|  | 	/** | ||||||
|  | 	 * Creates/gets an AbortController that triggers when the element disconnects | ||||||
|  | 	 * */ | ||||||
|  | 	signal: AbortSignal; | ||||||
|  | 	state: Scope[]; | ||||||
|  | 	/** Adds new child scope. All attributes are inherited by default. */ | ||||||
|  | 	push(scope?: Partial<Scope>): ReturnType<Array<Scope>["push"]>; | ||||||
|  | 	/** Adds root scope as a child of the current scope. */ | ||||||
|  | 	pushRoot(): ReturnType<Array<Scope>["push"]>; | ||||||
|  | 	/** Removes last/current child scope. */ | ||||||
|  | 	pop(): ReturnType<Array<Scope>["pop"]>; | ||||||
|  | }; | ||||||
|  | export function customElementRender<EL extends HTMLElement, P extends any = Record<string, string | Signal<string, {}>>>(target: ShadowRoot | EL, render: (props: P) => SupportedElement | DocumentFragment, props?: P | ((el: EL) => P)): EL; | ||||||
|  | export function customElementWithDDE<EL extends (new () => HTMLElement)>(custom_element: EL): EL; | ||||||
|  | export function lifecyclesToEvents<EL extends (new () => HTMLElement)>(custom_element: EL): EL; | ||||||
|  | /** | ||||||
|  |  * This is used primarly for server side rendering. To be sure that all async operations | ||||||
|  |  * are finished before the page is sent to the client. | ||||||
|  |  * ``` | ||||||
|  |  *	// on component | ||||||
|  |  *	function component(){ | ||||||
|  |  *		… | ||||||
|  |  *		queue(fetch(...).then(...)); | ||||||
|  |  *	} | ||||||
|  |  * | ||||||
|  |  * // building the page | ||||||
|  |  * async function build(){ | ||||||
|  |  *		const { component }= await import("./component.js"); | ||||||
|  |  *		document.body.append(el(component)); | ||||||
|  |  *		await queue(); | ||||||
|  |  *		retutn document.body.innerHTML; | ||||||
|  |  *	} | ||||||
|  |  * ``` | ||||||
|  |  * */ | ||||||
|  | export function queue(promise?: Promise<unknown>): Promise<unknown>; | ||||||
|  | /** | ||||||
|  |  * Memoization utility for caching DOM elements to improve performance. | ||||||
|  |  * Used to prevent unnecessary recreation of elements when rendering lists or complex components. | ||||||
|  |  * | ||||||
|  |  * @param key - Unique identifier for the element (usually an ID or unique value) | ||||||
|  |  * @param generator - Function that creates the element | ||||||
|  |  * @returns The cached element if the key exists, otherwise the result of the generator function | ||||||
|  |  * | ||||||
|  |  * @example | ||||||
|  |  * ```ts | ||||||
|  |  * // Within S.el for list rendering | ||||||
|  |  * S.el(itemsSignal, (items, memo) => | ||||||
|  |  *   el("ul").append( | ||||||
|  |  *     ...items.map(item => | ||||||
|  |  *       memo(item.id, () => el(ItemComponent, item)) | ||||||
|  |  *     ) | ||||||
|  |  *   ) | ||||||
|  |  * ) | ||||||
|  |  * ``` | ||||||
|  |  */ | ||||||
|  | export function memo<T>(key: string | number | object, generator: (key: any) => T): T; | ||||||
|  | /** | ||||||
|  |  * Memo namespace containing utility functions for memoization. | ||||||
|  |  */ | ||||||
|  | export namespace memo { | ||||||
|  | 	/** | ||||||
|  | 	 * Checks if an object is a memo scope. | ||||||
|  | 	 * @param obj - The object to check | ||||||
|  | 	 * @returns True if the object is a memo scope | ||||||
|  | 	 */ | ||||||
|  | 	export function isScope(obj: any): boolean; | ||||||
|  | 	/** | ||||||
|  | 	 * Creates a memoized function with optional cleanup support. | ||||||
|  | 	 * | ||||||
|  | 	 * @param fun - The function to memoize | ||||||
|  | 	 * @param options - Configuration options | ||||||
|  | 	 * @param options.signal - AbortSignal for cleanup | ||||||
|  | 	 * @param options.onlyLast - When true, only keeps the cache from the most recent call | ||||||
|  | 	 * @returns A memoized version of the function with a .clear() method | ||||||
|  | 	 * | ||||||
|  | 	 * @example | ||||||
|  | 	 * ```ts | ||||||
|  | 	 * const renderItems = memo.scope(function(items) { | ||||||
|  | 	 *	 return items.map(item => | ||||||
|  | 	 *		 memo(item.id, () => el("div", item.name)) | ||||||
|  | 	 *	 ); | ||||||
|  | 	 * }, { | ||||||
|  | 	 *	 signal: controller.signal, | ||||||
|  | 	 *	 onlyLast: true | ||||||
|  | 	 * }); | ||||||
|  | 	 * ``` | ||||||
|  | 	 */ | ||||||
|  | 	export function scope<F extends Function>(fun: F, options?: { | ||||||
|  | 		signal?: AbortSignal; | ||||||
|  | 		onlyLast?: boolean; | ||||||
|  | 	}): F & { | ||||||
|  | 		clear: () => void; | ||||||
|  | 	}; | ||||||
|  | } | ||||||
|  | /* TypeScript MEH */ | ||||||
|  | declare global { | ||||||
|  | 	type ddeAppend<el> = (...nodes: (Node | string)[]) => el; | ||||||
|  | 	interface ddeDocumentFragment extends DocumentFragment { | ||||||
|  | 		append: ddeAppend<ddeDocumentFragment>; | ||||||
|  | 	} | ||||||
|  | 	interface ddeHTMLElement extends HTMLElement { | ||||||
|  | 		append: ddeAppend<ddeHTMLElement>; | ||||||
|  | 	} | ||||||
|  | 	interface ddeSVGElement extends SVGElement { | ||||||
|  | 		append: ddeAppend<ddeSVGElement>; | ||||||
|  | 	} | ||||||
|  | 	interface ddeMathMLElement extends MathMLElement { | ||||||
|  | 		append: ddeAppend<ddeMathMLElement>; | ||||||
|  | 	} | ||||||
|  | 	interface ddeHTMLElementTagNameMap { | ||||||
|  | 		"a": ddeHTMLAnchorElement; | ||||||
|  | 		"area": ddeHTMLAreaElement; | ||||||
|  | 		"audio": ddeHTMLAudioElement; | ||||||
|  | 		"base": ddeHTMLBaseElement; | ||||||
|  | 		"blockquote": ddeHTMLQuoteElement; | ||||||
|  | 		"body": ddeHTMLBodyElement; | ||||||
|  | 		"br": ddeHTMLBRElement; | ||||||
|  | 		"button": ddeHTMLButtonElement; | ||||||
|  | 		"canvas": ddeHTMLCanvasElement; | ||||||
|  | 		"caption": ddeHTMLTableCaptionElement; | ||||||
|  | 		"col": ddeHTMLTableColElement; | ||||||
|  | 		"colgroup": ddeHTMLTableColElement; | ||||||
|  | 		"data": ddeHTMLDataElement; | ||||||
|  | 		"datalist": ddeHTMLDataListElement; | ||||||
|  | 		"del": ddeHTMLModElement; | ||||||
|  | 		"details": ddeHTMLDetailsElement; | ||||||
|  | 		"dialog": ddeHTMLDialogElement; | ||||||
|  | 		"div": ddeHTMLDivElement; | ||||||
|  | 		"dl": ddeHTMLDListElement; | ||||||
|  | 		"embed": ddeHTMLEmbedElement; | ||||||
|  | 		"fieldset": ddeHTMLFieldSetElement; | ||||||
|  | 		"form": ddeHTMLFormElement; | ||||||
|  | 		"h1": ddeHTMLHeadingElement; | ||||||
|  | 		"h2": ddeHTMLHeadingElement; | ||||||
|  | 		"h3": ddeHTMLHeadingElement; | ||||||
|  | 		"h4": ddeHTMLHeadingElement; | ||||||
|  | 		"h5": ddeHTMLHeadingElement; | ||||||
|  | 		"h6": ddeHTMLHeadingElement; | ||||||
|  | 		"head": ddeHTMLHeadElement; | ||||||
|  | 		"hr": ddeHTMLHRElement; | ||||||
|  | 		"html": ddeHTMLHtmlElement; | ||||||
|  | 		"iframe": ddeHTMLIFrameElement; | ||||||
|  | 		"img": ddeHTMLImageElement; | ||||||
|  | 		"input": ddeHTMLInputElement; | ||||||
|  | 		"ins": ddeHTMLModElement; | ||||||
|  | 		"label": ddeHTMLLabelElement; | ||||||
|  | 		"legend": ddeHTMLLegendElement; | ||||||
|  | 		"li": ddeHTMLLIElement; | ||||||
|  | 		"link": ddeHTMLLinkElement; | ||||||
|  | 		"map": ddeHTMLMapElement; | ||||||
|  | 		"menu": ddeHTMLMenuElement; | ||||||
|  | 		"meta": ddeHTMLMetaElement; | ||||||
|  | 		"meter": ddeHTMLMeterElement; | ||||||
|  | 		"object": ddeHTMLObjectElement; | ||||||
|  | 		"ol": ddeHTMLOListElement; | ||||||
|  | 		"optgroup": ddeHTMLOptGroupElement; | ||||||
|  | 		"option": ddeHTMLOptionElement; | ||||||
|  | 		"output": ddeHTMLOutputElement; | ||||||
|  | 		"p": ddeHTMLParagraphElement; | ||||||
|  | 		"picture": ddeHTMLPictureElement; | ||||||
|  | 		"pre": ddeHTMLPreElement; | ||||||
|  | 		"progress": ddeHTMLProgressElement; | ||||||
|  | 		"q": ddeHTMLQuoteElement; | ||||||
|  | 		"script": ddeHTMLScriptElement; | ||||||
|  | 		"select": ddeHTMLSelectElement; | ||||||
|  | 		"slot": ddeHTMLSlotElement; | ||||||
|  | 		"source": ddeHTMLSourceElement; | ||||||
|  | 		"span": ddeHTMLSpanElement; | ||||||
|  | 		"style": ddeHTMLStyleElement; | ||||||
|  | 		"table": ddeHTMLTableElement; | ||||||
|  | 		"tbody": ddeHTMLTableSectionElement; | ||||||
|  | 		"td": ddeHTMLTableCellElement; | ||||||
|  | 		"template": ddeHTMLTemplateElement; | ||||||
|  | 		"textarea": ddeHTMLTextAreaElement; | ||||||
|  | 		"tfoot": ddeHTMLTableSectionElement; | ||||||
|  | 		"th": ddeHTMLTableCellElement; | ||||||
|  | 		"thead": ddeHTMLTableSectionElement; | ||||||
|  | 		"time": ddeHTMLTimeElement; | ||||||
|  | 		"title": ddeHTMLTitleElement; | ||||||
|  | 		"tr": ddeHTMLTableRowElement; | ||||||
|  | 		"track": ddeHTMLTrackElement; | ||||||
|  | 		"ul": ddeHTMLUListElement; | ||||||
|  | 		"video": ddeHTMLVideoElement; | ||||||
|  | 	} | ||||||
|  | 	interface ddeSVGElementTagNameMap { | ||||||
|  | 		"a": ddeSVGAElement; | ||||||
|  | 		"animate": ddeSVGAnimateElement; | ||||||
|  | 		"animateMotion": ddeSVGAnimateMotionElement; | ||||||
|  | 		"animateTransform": ddeSVGAnimateTransformElement; | ||||||
|  | 		"circle": ddeSVGCircleElement; | ||||||
|  | 		"clipPath": ddeSVGClipPathElement; | ||||||
|  | 		"defs": ddeSVGDefsElement; | ||||||
|  | 		"desc": ddeSVGDescElement; | ||||||
|  | 		"ellipse": ddeSVGEllipseElement; | ||||||
|  | 		"feBlend": ddeSVGFEBlendElement; | ||||||
|  | 		"feColorMatrix": ddeSVGFEColorMatrixElement; | ||||||
|  | 		"feComponentTransfer": ddeSVGFEComponentTransferElement; | ||||||
|  | 		"feComposite": ddeSVGFECompositeElement; | ||||||
|  | 		"feConvolveMatrix": ddeSVGFEConvolveMatrixElement; | ||||||
|  | 		"feDiffuseLighting": ddeSVGFEDiffuseLightingElement; | ||||||
|  | 		"feDisplacementMap": ddeSVGFEDisplacementMapElement; | ||||||
|  | 		"feDistantLight": ddeSVGFEDistantLightElement; | ||||||
|  | 		"feDropShadow": ddeSVGFEDropShadowElement; | ||||||
|  | 		"feFlood": ddeSVGFEFloodElement; | ||||||
|  | 		"feFuncA": ddeSVGFEFuncAElement; | ||||||
|  | 		"feFuncB": ddeSVGFEFuncBElement; | ||||||
|  | 		"feFuncG": ddeSVGFEFuncGElement; | ||||||
|  | 		"feFuncR": ddeSVGFEFuncRElement; | ||||||
|  | 		"feGaussianBlur": ddeSVGFEGaussianBlurElement; | ||||||
|  | 		"feImage": ddeSVGFEImageElement; | ||||||
|  | 		"feMerge": ddeSVGFEMergeElement; | ||||||
|  | 		"feMergeNode": ddeSVGFEMergeNodeElement; | ||||||
|  | 		"feMorphology": ddeSVGFEMorphologyElement; | ||||||
|  | 		"feOffset": ddeSVGFEOffsetElement; | ||||||
|  | 		"fePointLight": ddeSVGFEPointLightElement; | ||||||
|  | 		"feSpecularLighting": ddeSVGFESpecularLightingElement; | ||||||
|  | 		"feSpotLight": ddeSVGFESpotLightElement; | ||||||
|  | 		"feTile": ddeSVGFETileElement; | ||||||
|  | 		"feTurbulence": ddeSVGFETurbulenceElement; | ||||||
|  | 		"filter": ddeSVGFilterElement; | ||||||
|  | 		"foreignObject": ddeSVGForeignObjectElement; | ||||||
|  | 		"g": ddeSVGGElement; | ||||||
|  | 		"image": ddeSVGImageElement; | ||||||
|  | 		"line": ddeSVGLineElement; | ||||||
|  | 		"linearGradient": ddeSVGLinearGradientElement; | ||||||
|  | 		"marker": ddeSVGMarkerElement; | ||||||
|  | 		"mask": ddeSVGMaskElement; | ||||||
|  | 		"metadata": ddeSVGMetadataElement; | ||||||
|  | 		"mpath": ddeSVGMPathElement; | ||||||
|  | 		"path": ddeSVGPathElement; | ||||||
|  | 		"pattern": ddeSVGPatternElement; | ||||||
|  | 		"polygon": ddeSVGPolygonElement; | ||||||
|  | 		"polyline": ddeSVGPolylineElement; | ||||||
|  | 		"radialGradient": ddeSVGRadialGradientElement; | ||||||
|  | 		"rect": ddeSVGRectElement; | ||||||
|  | 		"script": ddeSVGScriptElement; | ||||||
|  | 		"set": ddeSVGSetElement; | ||||||
|  | 		"stop": ddeSVGStopElement; | ||||||
|  | 		"style": ddeSVGStyleElement; | ||||||
|  | 		"svg": ddeSVGSVGElement; | ||||||
|  | 		"switch": ddeSVGSwitchElement; | ||||||
|  | 		"symbol": ddeSVGSymbolElement; | ||||||
|  | 		"text": ddeSVGTextElement; | ||||||
|  | 		"textPath": ddeSVGTextPathElement; | ||||||
|  | 		"title": ddeSVGTitleElement; | ||||||
|  | 		"tspan": ddeSVGTSpanElement; | ||||||
|  | 		"use": ddeSVGUseElement; | ||||||
|  | 		"view": ddeSVGViewElement; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | // editorconfig-checker-disable | ||||||
|  | export interface ddeHTMLAnchorElement extends HTMLAnchorElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLAnchorElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLAreaElement extends HTMLAreaElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLAreaElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLAudioElement extends HTMLAudioElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLAudioElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLBaseElement extends HTMLBaseElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLBaseElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLQuoteElement extends HTMLQuoteElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLQuoteElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLBodyElement extends HTMLBodyElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLBodyElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLBRElement extends HTMLBRElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLBRElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLButtonElement extends HTMLButtonElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLButtonElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLCanvasElement extends HTMLCanvasElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLCanvasElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLTableCaptionElement extends HTMLTableCaptionElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLTableCaptionElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLTableColElement extends HTMLTableColElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLTableColElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLTableColElement extends HTMLTableColElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLTableColElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLDataElement extends HTMLDataElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLDataElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLDataListElement extends HTMLDataListElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLDataListElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLModElement extends HTMLModElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLModElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLDetailsElement extends HTMLDetailsElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLDetailsElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLDialogElement extends HTMLDialogElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLDialogElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLDivElement extends HTMLDivElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLDivElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLDListElement extends HTMLDListElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLDListElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLEmbedElement extends HTMLEmbedElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLEmbedElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLFieldSetElement extends HTMLFieldSetElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLFieldSetElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLFormElement extends HTMLFormElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLFormElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLHeadingElement extends HTMLHeadingElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLHeadingElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLHeadElement extends HTMLHeadElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLHeadElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLHRElement extends HTMLHRElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLHRElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLHtmlElement extends HTMLHtmlElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLHtmlElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLIFrameElement extends HTMLIFrameElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLIFrameElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLImageElement extends HTMLImageElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLImageElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLInputElement extends HTMLInputElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLInputElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLLabelElement extends HTMLLabelElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLLabelElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLLegendElement extends HTMLLegendElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLLegendElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLLIElement extends HTMLLIElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLLIElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLLinkElement extends HTMLLinkElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLLinkElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLMapElement extends HTMLMapElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLMapElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLMenuElement extends HTMLMenuElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLMenuElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLMetaElement extends HTMLMetaElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLMetaElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLMeterElement extends HTMLMeterElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLMeterElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLObjectElement extends HTMLObjectElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLObjectElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLOListElement extends HTMLOListElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLOListElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLOptGroupElement extends HTMLOptGroupElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLOptGroupElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLOptionElement extends HTMLOptionElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLOptionElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLOutputElement extends HTMLOutputElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLOutputElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLParagraphElement extends HTMLParagraphElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLParagraphElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLPictureElement extends HTMLPictureElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLPictureElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLPreElement extends HTMLPreElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLPreElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLProgressElement extends HTMLProgressElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLProgressElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLScriptElement extends HTMLScriptElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLScriptElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLSelectElement extends HTMLSelectElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLSelectElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLSlotElement extends HTMLSlotElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLSlotElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLSourceElement extends HTMLSourceElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLSourceElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLSpanElement extends HTMLSpanElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLSpanElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLStyleElement extends HTMLStyleElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLStyleElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLTableElement extends HTMLTableElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLTableElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLTableSectionElement extends HTMLTableSectionElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLTableSectionElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLTableCellElement extends HTMLTableCellElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLTableCellElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLTemplateElement extends HTMLTemplateElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLTemplateElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLTextAreaElement extends HTMLTextAreaElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLTextAreaElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLTableCellElement extends HTMLTableCellElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLTableCellElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLTimeElement extends HTMLTimeElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLTimeElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLTitleElement extends HTMLTitleElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLTitleElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLTableRowElement extends HTMLTableRowElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLTableRowElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLTrackElement extends HTMLTrackElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLTrackElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLUListElement extends HTMLUListElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLUListElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLVideoElement extends HTMLVideoElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLVideoElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGAElement extends SVGAElement { | ||||||
|  | 	append: ddeAppend<ddeSVGAElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGAnimateElement extends SVGAnimateElement { | ||||||
|  | 	append: ddeAppend<ddeSVGAnimateElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGAnimateMotionElement extends SVGAnimateMotionElement { | ||||||
|  | 	append: ddeAppend<ddeSVGAnimateMotionElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGAnimateTransformElement extends SVGAnimateTransformElement { | ||||||
|  | 	append: ddeAppend<ddeSVGAnimateTransformElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGCircleElement extends SVGCircleElement { | ||||||
|  | 	append: ddeAppend<ddeSVGCircleElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGClipPathElement extends SVGClipPathElement { | ||||||
|  | 	append: ddeAppend<ddeSVGClipPathElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGDefsElement extends SVGDefsElement { | ||||||
|  | 	append: ddeAppend<ddeSVGDefsElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGDescElement extends SVGDescElement { | ||||||
|  | 	append: ddeAppend<ddeSVGDescElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGEllipseElement extends SVGEllipseElement { | ||||||
|  | 	append: ddeAppend<ddeSVGEllipseElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEBlendElement extends SVGFEBlendElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEBlendElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEColorMatrixElement extends SVGFEColorMatrixElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEColorMatrixElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEComponentTransferElement extends SVGFEComponentTransferElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEComponentTransferElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFECompositeElement extends SVGFECompositeElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFECompositeElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEConvolveMatrixElement extends SVGFEConvolveMatrixElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEConvolveMatrixElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEDiffuseLightingElement extends SVGFEDiffuseLightingElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEDiffuseLightingElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEDisplacementMapElement extends SVGFEDisplacementMapElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEDisplacementMapElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEDistantLightElement extends SVGFEDistantLightElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEDistantLightElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEDropShadowElement extends SVGFEDropShadowElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEDropShadowElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEFloodElement extends SVGFEFloodElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEFloodElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEFuncAElement extends SVGFEFuncAElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEFuncAElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEFuncBElement extends SVGFEFuncBElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEFuncBElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEFuncGElement extends SVGFEFuncGElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEFuncGElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEFuncRElement extends SVGFEFuncRElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEFuncRElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEGaussianBlurElement extends SVGFEGaussianBlurElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEGaussianBlurElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEImageElement extends SVGFEImageElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEImageElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEMergeElement extends SVGFEMergeElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEMergeElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEMergeNodeElement extends SVGFEMergeNodeElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEMergeNodeElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEMorphologyElement extends SVGFEMorphologyElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEMorphologyElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEOffsetElement extends SVGFEOffsetElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEOffsetElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEPointLightElement extends SVGFEPointLightElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEPointLightElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFESpecularLightingElement extends SVGFESpecularLightingElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFESpecularLightingElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFESpotLightElement extends SVGFESpotLightElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFESpotLightElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFETileElement extends SVGFETileElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFETileElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFETurbulenceElement extends SVGFETurbulenceElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFETurbulenceElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFilterElement extends SVGFilterElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFilterElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGForeignObjectElement extends SVGForeignObjectElement { | ||||||
|  | 	append: ddeAppend<ddeSVGForeignObjectElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGGElement extends SVGGElement { | ||||||
|  | 	append: ddeAppend<ddeSVGGElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGImageElement extends SVGImageElement { | ||||||
|  | 	append: ddeAppend<ddeSVGImageElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGLineElement extends SVGLineElement { | ||||||
|  | 	append: ddeAppend<ddeSVGLineElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGLinearGradientElement extends SVGLinearGradientElement { | ||||||
|  | 	append: ddeAppend<ddeSVGLinearGradientElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGMarkerElement extends SVGMarkerElement { | ||||||
|  | 	append: ddeAppend<ddeSVGMarkerElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGMaskElement extends SVGMaskElement { | ||||||
|  | 	append: ddeAppend<ddeSVGMaskElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGMetadataElement extends SVGMetadataElement { | ||||||
|  | 	append: ddeAppend<ddeSVGMetadataElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGMPathElement extends SVGMPathElement { | ||||||
|  | 	append: ddeAppend<ddeSVGMPathElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGPathElement extends SVGPathElement { | ||||||
|  | 	append: ddeAppend<ddeSVGPathElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGPatternElement extends SVGPatternElement { | ||||||
|  | 	append: ddeAppend<ddeSVGPatternElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGPolygonElement extends SVGPolygonElement { | ||||||
|  | 	append: ddeAppend<ddeSVGPolygonElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGPolylineElement extends SVGPolylineElement { | ||||||
|  | 	append: ddeAppend<ddeSVGPolylineElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGRadialGradientElement extends SVGRadialGradientElement { | ||||||
|  | 	append: ddeAppend<ddeSVGRadialGradientElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGRectElement extends SVGRectElement { | ||||||
|  | 	append: ddeAppend<ddeSVGRectElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGScriptElement extends SVGScriptElement { | ||||||
|  | 	append: ddeAppend<ddeSVGScriptElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGSetElement extends SVGSetElement { | ||||||
|  | 	append: ddeAppend<ddeSVGSetElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGStopElement extends SVGStopElement { | ||||||
|  | 	append: ddeAppend<ddeSVGStopElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGStyleElement extends SVGStyleElement { | ||||||
|  | 	append: ddeAppend<ddeSVGStyleElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGSVGElement extends SVGSVGElement { | ||||||
|  | 	append: ddeAppend<ddeSVGSVGElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGSwitchElement extends SVGSwitchElement { | ||||||
|  | 	append: ddeAppend<ddeSVGSwitchElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGSymbolElement extends SVGSymbolElement { | ||||||
|  | 	append: ddeAppend<ddeSVGSymbolElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGTextElement extends SVGTextElement { | ||||||
|  | 	append: ddeAppend<ddeSVGTextElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGTextPathElement extends SVGTextPathElement { | ||||||
|  | 	append: ddeAppend<ddeSVGTextPathElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGTitleElement extends SVGTitleElement { | ||||||
|  | 	append: ddeAppend<ddeSVGTitleElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGTSpanElement extends SVGTSpanElement { | ||||||
|  | 	append: ddeAppend<ddeSVGTSpanElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGUseElement extends SVGUseElement { | ||||||
|  | 	append: ddeAppend<ddeSVGUseElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGViewElement extends SVGViewElement { | ||||||
|  | 	append: ddeAppend<ddeSVGViewElement>; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | export { | ||||||
|  | 	dispatchEvent$1 as dispatchEvent, | ||||||
|  | 	el as createElement, | ||||||
|  | 	elNS as createElementNS, | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | export as namespace iife; | ||||||
|  |  | ||||||
|  | export {}; | ||||||
							
								
								
									
										1031
									
								
								dist/iife-with-signals.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1031
									
								
								dist/iife-with-signals.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										862
									
								
								dist/iife-with-signals.min.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										862
									
								
								dist/iife-with-signals.min.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,862 @@ | |||||||
|  | // Generated by dts-bundle-generator v9.5.1 | ||||||
|  |  | ||||||
|  | export interface Signal<V, A> { | ||||||
|  | 	/** The current value of the signal */ | ||||||
|  | 	get(): V; | ||||||
|  | 	/** Set new value of the signal */ | ||||||
|  | 	set(value: V, force?: boolean): V; | ||||||
|  | 	toJSON(): V; | ||||||
|  | 	valueOf(): V; | ||||||
|  | } | ||||||
|  | export type Action<V> = (this: { | ||||||
|  | 	value: V; | ||||||
|  | 	stopPropagation(): void; | ||||||
|  | }, ...a: any[]) => typeof signal._ | void; | ||||||
|  | //type SymbolSignal= Symbol; | ||||||
|  | export type SymbolOnclear = symbol; | ||||||
|  | export type Actions<V> = Record<string | SymbolOnclear, Action<V>>; | ||||||
|  | export type OnListenerOptions = Pick<AddEventListenerOptions, "signal"> & { | ||||||
|  | 	first_time?: boolean; | ||||||
|  | }; | ||||||
|  | export type SElement = Node | Element | DocumentFragment | ddeHTMLElement | ddeSVGElement | ddeDocumentFragment; | ||||||
|  | export interface signal { | ||||||
|  | 	_: Symbol; | ||||||
|  | 	/** | ||||||
|  | 	 * Computations signal. This creates a signal which is computed from other signals. | ||||||
|  | 	 * */ | ||||||
|  | 	<V extends () => any>(computation: V): Signal<ReturnType<V>, {}>; | ||||||
|  | 	/** | ||||||
|  | 	 * Simple example: | ||||||
|  | 	 * ```js | ||||||
|  | 	 * const hello= S("Hello Signal"); | ||||||
|  | 	 * ``` | ||||||
|  | 	 * …simple todo signal: | ||||||
|  | 	 * ```js | ||||||
|  | 	 * const todos= S([], { | ||||||
|  | 	 * 	add(v){ this.value.push(S(v)); }, | ||||||
|  | 	 * 	remove(i){ this.value.splice(i, 1); }, | ||||||
|  | 	 * 	[S.symbols.onclear](){ S.clear(...this.value); }, | ||||||
|  | 	 * }); | ||||||
|  | 	 * ``` | ||||||
|  | 	 * …computed signal: | ||||||
|  | 	 * ```js | ||||||
|  | 	 * const name= S("Jan"); | ||||||
|  | 	 * const surname= S("Andrle"); | ||||||
|  | 	 * const fullname= S(()=> name.get()+" "+surname.get()); | ||||||
|  | 	 * ``` | ||||||
|  | 	 * @param value Initial signal value. Or function computing value from other signals. | ||||||
|  | 	 * @param actions Use to define actions on the signal. Such as add item to the array. | ||||||
|  | 	 *		There is also a reserved function `S.symbol.onclear` which is called when the signal is cleared | ||||||
|  | 	 *		by `S.clear`. | ||||||
|  | 	 * */ | ||||||
|  | 	<V, A extends Actions<V>>(value: V, actions?: A): Signal<V, A>; | ||||||
|  | 	action<S extends Signal<any, Actions<any>>, A extends (S extends Signal<any, infer A> ? A : never), N extends keyof A>(signal: S, name: N, ...params: A[N] extends (...args: infer P) => any ? P : never): void; | ||||||
|  | 	clear(...signals: Signal<any, any>[]): void; | ||||||
|  | 	on<T>(signal: Signal<T, any>, onchange: (a: T) => void, options?: OnListenerOptions): void; | ||||||
|  | 	symbols: { | ||||||
|  | 		//signal: SymbolSignal; | ||||||
|  | 		onclear: SymbolOnclear; | ||||||
|  | 	}; | ||||||
|  | 	/** | ||||||
|  | 	 * Reactive element, which is rendered based on the given signal. | ||||||
|  | 	 * ```js | ||||||
|  | 	 * S.el(signal, value=> value ? el("b", "True") : el("i", "False")); | ||||||
|  | 	 * S.el(listS, list=> list.map(li=> el("li", li))); | ||||||
|  | 	 * ``` | ||||||
|  | 	 * */ | ||||||
|  | 	el<S extends any>(signal: Signal<S, any>, el: (v: S) => SElement | SElement[]): DocumentFragment; | ||||||
|  | 	observedAttributes(custom_element: HTMLElement): Record<string, Signal<string, {}>>; | ||||||
|  | } | ||||||
|  | export const signal: signal; | ||||||
|  | export const S: signal; | ||||||
|  | declare global { | ||||||
|  | 	type ddeSignal<T, A = {}> = Signal<T, A>; | ||||||
|  | 	type ddeAction<V> = Action<V>; | ||||||
|  | 	type ddeActions<V> = Actions<V>; | ||||||
|  | } | ||||||
|  | export type CustomElementTagNameMap = { | ||||||
|  | 	"#text": Text; | ||||||
|  | 	"#comment": Comment; | ||||||
|  | }; | ||||||
|  | export type SupportedElement = HTMLElementTagNameMap[keyof HTMLElementTagNameMap] | SVGElementTagNameMap[keyof SVGElementTagNameMap] | MathMLElementTagNameMap[keyof MathMLElementTagNameMap] | CustomElementTagNameMap[keyof CustomElementTagNameMap]; | ||||||
|  | declare global { | ||||||
|  | 	type ddeComponentAttributes = Record<any, any> | undefined; | ||||||
|  | 	type ddeElementAddon<El extends SupportedElement | DocumentFragment | Node> = (element: El, ...rest: any) => any; | ||||||
|  | 	type ddeString = string | Signal<string, {}>; | ||||||
|  | 	type ddeStringable = ddeString | number | Signal<number, {}>; | ||||||
|  | } | ||||||
|  | export type Host<EL extends SupportedElement> = (...addons: ddeElementAddon<EL>[]) => EL; | ||||||
|  | export type PascalCase = `${Capitalize<string>}${string}`; | ||||||
|  | export type AttrsModified = { | ||||||
|  | 	/** | ||||||
|  | 	 * Use string like in HTML (internally uses `*.setAttribute("style", *)`), or object representation (like DOM API). | ||||||
|  | 	 */ | ||||||
|  | 	style: Partial<CSSStyleDeclaration> | ddeString | Partial<{ | ||||||
|  | 		[K in keyof CSSStyleDeclaration]: Signal<CSSStyleDeclaration[K], {}>; | ||||||
|  | 	}>; | ||||||
|  | 	/** | ||||||
|  | 	 * Provide option to add/remove/toggle CSS clasess (index of object) using 1/0/-1. | ||||||
|  | 	 * In fact `el.classList.toggle(class_name)` for `-1` and `el.classList.toggle(class_name, Boolean(...))` | ||||||
|  | 	 * for others. | ||||||
|  | 	 */ | ||||||
|  | 	classList: Record<string, -1 | 0 | 1 | boolean | Signal<-1 | 0 | 1 | boolean, {}>>; | ||||||
|  | 	/** | ||||||
|  | 	 * Used by the dataset HTML attribute to represent data for custom attributes added to elements. | ||||||
|  | 	 * Values are converted to string (see {@link DOMStringMap}). | ||||||
|  | 	 * | ||||||
|  | 	 * [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMStringMap) | ||||||
|  | 	 * */ | ||||||
|  | 	dataset: Record<string, ddeStringable>; | ||||||
|  | 	/** | ||||||
|  | 	 * Sets `aria-*` simiraly to `dataset` | ||||||
|  | 	 * */ | ||||||
|  | 	ariaset: Record<string, ddeString>; | ||||||
|  | } & Record<`=${string}` | `data${PascalCase}` | `aria${PascalCase}`, ddeString> & Record<`.${string}`, any>; | ||||||
|  | export type _fromElsInterfaces<EL extends SupportedElement> = Omit<EL, keyof AttrsModified>; | ||||||
|  | export type IsReadonly<T, K extends keyof T> = T extends { | ||||||
|  | 	readonly [P in K]: T[K]; | ||||||
|  | } ? true : false; | ||||||
|  | /** | ||||||
|  |  * Just element attributtes | ||||||
|  |  * | ||||||
|  |  * In most cases, you can use native propertie such as | ||||||
|  |  * [MDN WEB/API/Element](https://developer.mozilla.org/en-US/docs/Web/API/Element) and so on | ||||||
|  |  * (e.g. [`Text`](https://developer.mozilla.org/en-US/docs/Web/API/Text)). | ||||||
|  |  * | ||||||
|  |  * There is added support for `data[A-Z].*`/`aria[A-Z].*` to be converted to the kebab-case alternatives. | ||||||
|  |  * @private | ||||||
|  |  */ | ||||||
|  | export type ElementAttributes<T extends SupportedElement> = Partial<{ | ||||||
|  | 	[K in keyof _fromElsInterfaces<T>]: _fromElsInterfaces<T>[K] extends ((...p: any[]) => any) ? _fromElsInterfaces<T>[K] | ((...p: Parameters<_fromElsInterfaces<T>[K]>) => Signal<ReturnType<_fromElsInterfaces<T>[K]>, {}>) : (IsReadonly<_fromElsInterfaces<T>, K> extends false ? _fromElsInterfaces<T>[K] | Signal<_fromElsInterfaces<T>[K], {}> : ddeStringable); | ||||||
|  | } & AttrsModified> & Record<string, any>; | ||||||
|  | export function classListDeclarative<El extends SupportedElement>(element: El, classList: AttrsModified["classList"]): El; | ||||||
|  | export function assign<El extends SupportedElement>(element: El, ...attrs_array: ElementAttributes<El>[]): El; | ||||||
|  | export function assignAttribute<El extends SupportedElement, ATT extends keyof ElementAttributes<El>>(element: El, attr: ATT, value: ElementAttributes<El>[ATT]): ElementAttributes<El>[ATT]; | ||||||
|  | export type ExtendedHTMLElementTagNameMap = HTMLElementTagNameMap & CustomElementTagNameMap; | ||||||
|  | export namespace el { | ||||||
|  | 	/** | ||||||
|  | 	 * Creates a marker comment for elements | ||||||
|  | 	 * | ||||||
|  | 	 * @param attrs - Marker attributes | ||||||
|  | 	 * @param [is_open=false] - Whether the marker is open-ended | ||||||
|  | 	 * @returns Comment node marker | ||||||
|  | 	 */ | ||||||
|  | 	export function mark(attrs: { | ||||||
|  | 		type: "component" | "reactive" | "later"; | ||||||
|  | 		name?: string; | ||||||
|  | 		host?: "this" | "parentElement"; | ||||||
|  | 	}, is_open?: boolean): Comment; | ||||||
|  | } | ||||||
|  | export function chainableAppend<EL extends SupportedElement>(el: EL): EL | ddeHTMLElement; | ||||||
|  | export function el<A extends ddeComponentAttributes, EL extends SupportedElement | ddeDocumentFragment>(component: (attr: A, ...rest: any[]) => EL, attrs?: NoInfer<A>, ...addons: ddeElementAddon<EL>[]): EL extends ddeHTMLElementTagNameMap[keyof ddeHTMLElementTagNameMap] ? EL : (EL extends ddeDocumentFragment ? EL : ddeHTMLElement); | ||||||
|  | export function el<A extends { | ||||||
|  | 	textContent: ddeStringable; | ||||||
|  | }, EL extends SupportedElement | ddeDocumentFragment>(component: (attr: A, ...rest: any[]) => EL, attrs?: NoInfer<A>["textContent"], ...addons: ddeElementAddon<EL>[]): EL extends ddeHTMLElementTagNameMap[keyof ddeHTMLElementTagNameMap] ? EL : (EL extends ddeDocumentFragment ? EL : ddeHTMLElement); | ||||||
|  | export function el<TAG extends keyof ExtendedHTMLElementTagNameMap>(tag_name: TAG, attrs?: ElementAttributes<ExtendedHTMLElementTagNameMap[NoInfer<TAG>]> | ddeStringable, ...addons: ddeElementAddon<ExtendedHTMLElementTagNameMap[NoInfer<TAG>]>[]): TAG extends keyof ddeHTMLElementTagNameMap ? ddeHTMLElementTagNameMap[TAG] : ddeHTMLElement; | ||||||
|  | export function el(tag_name?: "<>"): ddeDocumentFragment; | ||||||
|  | export function el(tag_name: string, attrs?: ElementAttributes<HTMLElement> | ddeStringable, ...addons: ddeElementAddon<HTMLElement>[]): ddeHTMLElement; | ||||||
|  | export function elNS(namespace: "http://www.w3.org/2000/svg"): <TAG extends keyof SVGElementTagNameMap & string, EL extends (TAG extends keyof SVGElementTagNameMap ? SVGElementTagNameMap[TAG] : SVGElement)>(tag_name: TAG, attrs?: ElementAttributes<NoInfer<EL>> | ddeStringable, ...addons: ddeElementAddon<NoInfer<EL>>[]) => TAG extends keyof ddeSVGElementTagNameMap ? ddeSVGElementTagNameMap[TAG] : ddeSVGElement; | ||||||
|  | export function elNS(namespace: "http://www.w3.org/1998/Math/MathML"): <TAG extends keyof MathMLElementTagNameMap & string, EL extends (TAG extends keyof MathMLElementTagNameMap ? MathMLElementTagNameMap[TAG] : MathMLElement)>(tag_name: TAG, attrs?: ddeStringable | Partial<{ | ||||||
|  | 	[key in keyof EL]: EL[key] | Signal<EL[key], {}> | string | number | boolean; | ||||||
|  | }>, ...addons: ddeElementAddon<NoInfer<EL>>[]) => ddeMathMLElement; | ||||||
|  | export function elNS(namespace: string): (tag_name: string, attrs?: string | ddeStringable | Record<string, any>, ...addons: ddeElementAddon<SupportedElement>[]) => SupportedElement; | ||||||
|  | /** Simulate slots for ddeComponents */ | ||||||
|  | export function simulateSlots<EL extends SupportedElement | DocumentFragment>(root: EL): EL; | ||||||
|  | /** | ||||||
|  |  * Simulate slots in Custom Elements without using `shadowRoot`. | ||||||
|  |  * @param el Custom Element root element | ||||||
|  |  * @param body Body of the custom element | ||||||
|  |  * */ | ||||||
|  | export function simulateSlots<EL extends SupportedElement | DocumentFragment>(el: HTMLElement, body: EL): EL; | ||||||
|  | declare function dispatchEvent$1(name: keyof DocumentEventMap | string, host: Host<SupportedElement>): (data?: any) => void; | ||||||
|  | declare function dispatchEvent$1(name: keyof DocumentEventMap | string, options?: EventInit): (element: SupportedElement, data?: any) => void; | ||||||
|  | declare function dispatchEvent$1(name: keyof DocumentEventMap | string, options: EventInit | null, host: Host<SupportedElement>): (data?: any) => void; | ||||||
|  | export interface On { | ||||||
|  | 	/** Listens to the DOM event. See {@link Document.addEventListener} */ | ||||||
|  | 	<Event extends keyof DocumentEventMap, EL extends SupportedElement>(type: Event, listener: (this: EL, ev: DocumentEventMap[Event] & { | ||||||
|  | 		target: EL; | ||||||
|  | 	}) => any, options?: AddEventListenerOptions): ddeElementAddon<EL>; | ||||||
|  | 	<EE extends ddeElementAddon<SupportedElement> = ddeElementAddon<HTMLElement>>(type: string, listener: (this: EE extends ddeElementAddon<infer El> ? El : never, ev: Event | CustomEvent) => any, options?: AddEventListenerOptions): EE; | ||||||
|  | 	/** Listens to the element is connected to the live DOM. In case of custom elements uses [`connectedCallback`](https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_custom_elements#custom_element_lifecycle_callbacks), or {@link MutationObserver} else where */ // editorconfig-checker-disable-line | ||||||
|  | 	connected<EL extends SupportedElement>(listener: (this: EL, event: CustomEvent<NoInfer<EL>>) => any, options?: AddEventListenerOptions): ddeElementAddon<EL>; | ||||||
|  | 	/** Listens to the element is disconnected from the live DOM. In case of custom elements uses [`disconnectedCallback`](https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_custom_elements#custom_element_lifecycle_callbacks), or {@link MutationObserver} else where */ // editorconfig-checker-disable-line | ||||||
|  | 	disconnected<EL extends SupportedElement>(listener: (this: EL, event: CustomEvent<void>) => any, options?: AddEventListenerOptions): ddeElementAddon<EL>; | ||||||
|  | 	/** | ||||||
|  | 	 * Fires after the next tick of the Javascript event loop. | ||||||
|  | 	 * This is handy for example to apply some property depending on the element content: | ||||||
|  | 	 * ```js | ||||||
|  | 	 * const selected= "Z"; | ||||||
|  | 	 * //... | ||||||
|  | 	 * return el("form").append( | ||||||
|  | 	 *		el("select", null, on.defer(e=> e.value=selected)).append( | ||||||
|  | 	 *			el("option", { value: "A", textContent: "A" }), | ||||||
|  | 	 *			//... | ||||||
|  | 	 *			el("option", { value: "Z", textContent: "Z" }), | ||||||
|  | 	 *		), | ||||||
|  | 	 * ); | ||||||
|  | 	 * ``` | ||||||
|  | 	 * */ | ||||||
|  | 	defer<EL extends SupportedElement>(listener: (element: EL) => any): ddeElementAddon<EL>; | ||||||
|  | } | ||||||
|  | export const on: On; | ||||||
|  | export type Scope = { | ||||||
|  | 	scope: Node | Function | Object; | ||||||
|  | 	host: Host<SupportedElement>; | ||||||
|  | 	custom_element: false | HTMLElement; | ||||||
|  | 	prevent: boolean; | ||||||
|  | }; | ||||||
|  | /** Current scope created last time the `el(Function)` was invoke. (Or {@link scope.push}) */ | ||||||
|  | export const scope: { | ||||||
|  | 	current: Scope; | ||||||
|  | 	/** Stops all automatizations. E. g. signals used as attributes in current scope | ||||||
|  | 	 * registers removing these listeners (and clean signal if no other listeners are detected) | ||||||
|  | 	 * on `disconnected` event. */ | ||||||
|  | 	preventDefault<T extends boolean>(prevent: T): T; | ||||||
|  | 	/** | ||||||
|  | 	 * This represents reference to the current host element — `scope.host()`. | ||||||
|  | 	 * It can be also used to register Addon(s) (functions to be called when component is initized) | ||||||
|  | 	 * — `scope.host(on.connected(console.log))`. | ||||||
|  | 	 * */ | ||||||
|  | 	host: Host<SupportedElement>; | ||||||
|  | 	/** | ||||||
|  | 	 * Creates/gets an AbortController that triggers when the element disconnects | ||||||
|  | 	 * */ | ||||||
|  | 	signal: AbortSignal; | ||||||
|  | 	state: Scope[]; | ||||||
|  | 	/** Adds new child scope. All attributes are inherited by default. */ | ||||||
|  | 	push(scope?: Partial<Scope>): ReturnType<Array<Scope>["push"]>; | ||||||
|  | 	/** Adds root scope as a child of the current scope. */ | ||||||
|  | 	pushRoot(): ReturnType<Array<Scope>["push"]>; | ||||||
|  | 	/** Removes last/current child scope. */ | ||||||
|  | 	pop(): ReturnType<Array<Scope>["pop"]>; | ||||||
|  | }; | ||||||
|  | export function customElementRender<EL extends HTMLElement, P extends any = Record<string, string | Signal<string, {}>>>(target: ShadowRoot | EL, render: (props: P) => SupportedElement | DocumentFragment, props?: P | ((el: EL) => P)): EL; | ||||||
|  | export function customElementWithDDE<EL extends (new () => HTMLElement)>(custom_element: EL): EL; | ||||||
|  | export function lifecyclesToEvents<EL extends (new () => HTMLElement)>(custom_element: EL): EL; | ||||||
|  | /** | ||||||
|  |  * This is used primarly for server side rendering. To be sure that all async operations | ||||||
|  |  * are finished before the page is sent to the client. | ||||||
|  |  * ``` | ||||||
|  |  *	// on component | ||||||
|  |  *	function component(){ | ||||||
|  |  *		… | ||||||
|  |  *		queue(fetch(...).then(...)); | ||||||
|  |  *	} | ||||||
|  |  * | ||||||
|  |  * // building the page | ||||||
|  |  * async function build(){ | ||||||
|  |  *		const { component }= await import("./component.js"); | ||||||
|  |  *		document.body.append(el(component)); | ||||||
|  |  *		await queue(); | ||||||
|  |  *		retutn document.body.innerHTML; | ||||||
|  |  *	} | ||||||
|  |  * ``` | ||||||
|  |  * */ | ||||||
|  | export function queue(promise?: Promise<unknown>): Promise<unknown>; | ||||||
|  | /** | ||||||
|  |  * Memoization utility for caching DOM elements to improve performance. | ||||||
|  |  * Used to prevent unnecessary recreation of elements when rendering lists or complex components. | ||||||
|  |  * | ||||||
|  |  * @param key - Unique identifier for the element (usually an ID or unique value) | ||||||
|  |  * @param generator - Function that creates the element | ||||||
|  |  * @returns The cached element if the key exists, otherwise the result of the generator function | ||||||
|  |  * | ||||||
|  |  * @example | ||||||
|  |  * ```ts | ||||||
|  |  * // Within S.el for list rendering | ||||||
|  |  * S.el(itemsSignal, (items, memo) => | ||||||
|  |  *   el("ul").append( | ||||||
|  |  *     ...items.map(item => | ||||||
|  |  *       memo(item.id, () => el(ItemComponent, item)) | ||||||
|  |  *     ) | ||||||
|  |  *   ) | ||||||
|  |  * ) | ||||||
|  |  * ``` | ||||||
|  |  */ | ||||||
|  | export function memo<T>(key: string | number | object, generator: (key: any) => T): T; | ||||||
|  | /** | ||||||
|  |  * Memo namespace containing utility functions for memoization. | ||||||
|  |  */ | ||||||
|  | export namespace memo { | ||||||
|  | 	/** | ||||||
|  | 	 * Checks if an object is a memo scope. | ||||||
|  | 	 * @param obj - The object to check | ||||||
|  | 	 * @returns True if the object is a memo scope | ||||||
|  | 	 */ | ||||||
|  | 	export function isScope(obj: any): boolean; | ||||||
|  | 	/** | ||||||
|  | 	 * Creates a memoized function with optional cleanup support. | ||||||
|  | 	 * | ||||||
|  | 	 * @param fun - The function to memoize | ||||||
|  | 	 * @param options - Configuration options | ||||||
|  | 	 * @param options.signal - AbortSignal for cleanup | ||||||
|  | 	 * @param options.onlyLast - When true, only keeps the cache from the most recent call | ||||||
|  | 	 * @returns A memoized version of the function with a .clear() method | ||||||
|  | 	 * | ||||||
|  | 	 * @example | ||||||
|  | 	 * ```ts | ||||||
|  | 	 * const renderItems = memo.scope(function(items) { | ||||||
|  | 	 *	 return items.map(item => | ||||||
|  | 	 *		 memo(item.id, () => el("div", item.name)) | ||||||
|  | 	 *	 ); | ||||||
|  | 	 * }, { | ||||||
|  | 	 *	 signal: controller.signal, | ||||||
|  | 	 *	 onlyLast: true | ||||||
|  | 	 * }); | ||||||
|  | 	 * ``` | ||||||
|  | 	 */ | ||||||
|  | 	export function scope<F extends Function>(fun: F, options?: { | ||||||
|  | 		signal?: AbortSignal; | ||||||
|  | 		onlyLast?: boolean; | ||||||
|  | 	}): F & { | ||||||
|  | 		clear: () => void; | ||||||
|  | 	}; | ||||||
|  | } | ||||||
|  | /* TypeScript MEH */ | ||||||
|  | declare global { | ||||||
|  | 	type ddeAppend<el> = (...nodes: (Node | string)[]) => el; | ||||||
|  | 	interface ddeDocumentFragment extends DocumentFragment { | ||||||
|  | 		append: ddeAppend<ddeDocumentFragment>; | ||||||
|  | 	} | ||||||
|  | 	interface ddeHTMLElement extends HTMLElement { | ||||||
|  | 		append: ddeAppend<ddeHTMLElement>; | ||||||
|  | 	} | ||||||
|  | 	interface ddeSVGElement extends SVGElement { | ||||||
|  | 		append: ddeAppend<ddeSVGElement>; | ||||||
|  | 	} | ||||||
|  | 	interface ddeMathMLElement extends MathMLElement { | ||||||
|  | 		append: ddeAppend<ddeMathMLElement>; | ||||||
|  | 	} | ||||||
|  | 	interface ddeHTMLElementTagNameMap { | ||||||
|  | 		"a": ddeHTMLAnchorElement; | ||||||
|  | 		"area": ddeHTMLAreaElement; | ||||||
|  | 		"audio": ddeHTMLAudioElement; | ||||||
|  | 		"base": ddeHTMLBaseElement; | ||||||
|  | 		"blockquote": ddeHTMLQuoteElement; | ||||||
|  | 		"body": ddeHTMLBodyElement; | ||||||
|  | 		"br": ddeHTMLBRElement; | ||||||
|  | 		"button": ddeHTMLButtonElement; | ||||||
|  | 		"canvas": ddeHTMLCanvasElement; | ||||||
|  | 		"caption": ddeHTMLTableCaptionElement; | ||||||
|  | 		"col": ddeHTMLTableColElement; | ||||||
|  | 		"colgroup": ddeHTMLTableColElement; | ||||||
|  | 		"data": ddeHTMLDataElement; | ||||||
|  | 		"datalist": ddeHTMLDataListElement; | ||||||
|  | 		"del": ddeHTMLModElement; | ||||||
|  | 		"details": ddeHTMLDetailsElement; | ||||||
|  | 		"dialog": ddeHTMLDialogElement; | ||||||
|  | 		"div": ddeHTMLDivElement; | ||||||
|  | 		"dl": ddeHTMLDListElement; | ||||||
|  | 		"embed": ddeHTMLEmbedElement; | ||||||
|  | 		"fieldset": ddeHTMLFieldSetElement; | ||||||
|  | 		"form": ddeHTMLFormElement; | ||||||
|  | 		"h1": ddeHTMLHeadingElement; | ||||||
|  | 		"h2": ddeHTMLHeadingElement; | ||||||
|  | 		"h3": ddeHTMLHeadingElement; | ||||||
|  | 		"h4": ddeHTMLHeadingElement; | ||||||
|  | 		"h5": ddeHTMLHeadingElement; | ||||||
|  | 		"h6": ddeHTMLHeadingElement; | ||||||
|  | 		"head": ddeHTMLHeadElement; | ||||||
|  | 		"hr": ddeHTMLHRElement; | ||||||
|  | 		"html": ddeHTMLHtmlElement; | ||||||
|  | 		"iframe": ddeHTMLIFrameElement; | ||||||
|  | 		"img": ddeHTMLImageElement; | ||||||
|  | 		"input": ddeHTMLInputElement; | ||||||
|  | 		"ins": ddeHTMLModElement; | ||||||
|  | 		"label": ddeHTMLLabelElement; | ||||||
|  | 		"legend": ddeHTMLLegendElement; | ||||||
|  | 		"li": ddeHTMLLIElement; | ||||||
|  | 		"link": ddeHTMLLinkElement; | ||||||
|  | 		"map": ddeHTMLMapElement; | ||||||
|  | 		"menu": ddeHTMLMenuElement; | ||||||
|  | 		"meta": ddeHTMLMetaElement; | ||||||
|  | 		"meter": ddeHTMLMeterElement; | ||||||
|  | 		"object": ddeHTMLObjectElement; | ||||||
|  | 		"ol": ddeHTMLOListElement; | ||||||
|  | 		"optgroup": ddeHTMLOptGroupElement; | ||||||
|  | 		"option": ddeHTMLOptionElement; | ||||||
|  | 		"output": ddeHTMLOutputElement; | ||||||
|  | 		"p": ddeHTMLParagraphElement; | ||||||
|  | 		"picture": ddeHTMLPictureElement; | ||||||
|  | 		"pre": ddeHTMLPreElement; | ||||||
|  | 		"progress": ddeHTMLProgressElement; | ||||||
|  | 		"q": ddeHTMLQuoteElement; | ||||||
|  | 		"script": ddeHTMLScriptElement; | ||||||
|  | 		"select": ddeHTMLSelectElement; | ||||||
|  | 		"slot": ddeHTMLSlotElement; | ||||||
|  | 		"source": ddeHTMLSourceElement; | ||||||
|  | 		"span": ddeHTMLSpanElement; | ||||||
|  | 		"style": ddeHTMLStyleElement; | ||||||
|  | 		"table": ddeHTMLTableElement; | ||||||
|  | 		"tbody": ddeHTMLTableSectionElement; | ||||||
|  | 		"td": ddeHTMLTableCellElement; | ||||||
|  | 		"template": ddeHTMLTemplateElement; | ||||||
|  | 		"textarea": ddeHTMLTextAreaElement; | ||||||
|  | 		"tfoot": ddeHTMLTableSectionElement; | ||||||
|  | 		"th": ddeHTMLTableCellElement; | ||||||
|  | 		"thead": ddeHTMLTableSectionElement; | ||||||
|  | 		"time": ddeHTMLTimeElement; | ||||||
|  | 		"title": ddeHTMLTitleElement; | ||||||
|  | 		"tr": ddeHTMLTableRowElement; | ||||||
|  | 		"track": ddeHTMLTrackElement; | ||||||
|  | 		"ul": ddeHTMLUListElement; | ||||||
|  | 		"video": ddeHTMLVideoElement; | ||||||
|  | 	} | ||||||
|  | 	interface ddeSVGElementTagNameMap { | ||||||
|  | 		"a": ddeSVGAElement; | ||||||
|  | 		"animate": ddeSVGAnimateElement; | ||||||
|  | 		"animateMotion": ddeSVGAnimateMotionElement; | ||||||
|  | 		"animateTransform": ddeSVGAnimateTransformElement; | ||||||
|  | 		"circle": ddeSVGCircleElement; | ||||||
|  | 		"clipPath": ddeSVGClipPathElement; | ||||||
|  | 		"defs": ddeSVGDefsElement; | ||||||
|  | 		"desc": ddeSVGDescElement; | ||||||
|  | 		"ellipse": ddeSVGEllipseElement; | ||||||
|  | 		"feBlend": ddeSVGFEBlendElement; | ||||||
|  | 		"feColorMatrix": ddeSVGFEColorMatrixElement; | ||||||
|  | 		"feComponentTransfer": ddeSVGFEComponentTransferElement; | ||||||
|  | 		"feComposite": ddeSVGFECompositeElement; | ||||||
|  | 		"feConvolveMatrix": ddeSVGFEConvolveMatrixElement; | ||||||
|  | 		"feDiffuseLighting": ddeSVGFEDiffuseLightingElement; | ||||||
|  | 		"feDisplacementMap": ddeSVGFEDisplacementMapElement; | ||||||
|  | 		"feDistantLight": ddeSVGFEDistantLightElement; | ||||||
|  | 		"feDropShadow": ddeSVGFEDropShadowElement; | ||||||
|  | 		"feFlood": ddeSVGFEFloodElement; | ||||||
|  | 		"feFuncA": ddeSVGFEFuncAElement; | ||||||
|  | 		"feFuncB": ddeSVGFEFuncBElement; | ||||||
|  | 		"feFuncG": ddeSVGFEFuncGElement; | ||||||
|  | 		"feFuncR": ddeSVGFEFuncRElement; | ||||||
|  | 		"feGaussianBlur": ddeSVGFEGaussianBlurElement; | ||||||
|  | 		"feImage": ddeSVGFEImageElement; | ||||||
|  | 		"feMerge": ddeSVGFEMergeElement; | ||||||
|  | 		"feMergeNode": ddeSVGFEMergeNodeElement; | ||||||
|  | 		"feMorphology": ddeSVGFEMorphologyElement; | ||||||
|  | 		"feOffset": ddeSVGFEOffsetElement; | ||||||
|  | 		"fePointLight": ddeSVGFEPointLightElement; | ||||||
|  | 		"feSpecularLighting": ddeSVGFESpecularLightingElement; | ||||||
|  | 		"feSpotLight": ddeSVGFESpotLightElement; | ||||||
|  | 		"feTile": ddeSVGFETileElement; | ||||||
|  | 		"feTurbulence": ddeSVGFETurbulenceElement; | ||||||
|  | 		"filter": ddeSVGFilterElement; | ||||||
|  | 		"foreignObject": ddeSVGForeignObjectElement; | ||||||
|  | 		"g": ddeSVGGElement; | ||||||
|  | 		"image": ddeSVGImageElement; | ||||||
|  | 		"line": ddeSVGLineElement; | ||||||
|  | 		"linearGradient": ddeSVGLinearGradientElement; | ||||||
|  | 		"marker": ddeSVGMarkerElement; | ||||||
|  | 		"mask": ddeSVGMaskElement; | ||||||
|  | 		"metadata": ddeSVGMetadataElement; | ||||||
|  | 		"mpath": ddeSVGMPathElement; | ||||||
|  | 		"path": ddeSVGPathElement; | ||||||
|  | 		"pattern": ddeSVGPatternElement; | ||||||
|  | 		"polygon": ddeSVGPolygonElement; | ||||||
|  | 		"polyline": ddeSVGPolylineElement; | ||||||
|  | 		"radialGradient": ddeSVGRadialGradientElement; | ||||||
|  | 		"rect": ddeSVGRectElement; | ||||||
|  | 		"script": ddeSVGScriptElement; | ||||||
|  | 		"set": ddeSVGSetElement; | ||||||
|  | 		"stop": ddeSVGStopElement; | ||||||
|  | 		"style": ddeSVGStyleElement; | ||||||
|  | 		"svg": ddeSVGSVGElement; | ||||||
|  | 		"switch": ddeSVGSwitchElement; | ||||||
|  | 		"symbol": ddeSVGSymbolElement; | ||||||
|  | 		"text": ddeSVGTextElement; | ||||||
|  | 		"textPath": ddeSVGTextPathElement; | ||||||
|  | 		"title": ddeSVGTitleElement; | ||||||
|  | 		"tspan": ddeSVGTSpanElement; | ||||||
|  | 		"use": ddeSVGUseElement; | ||||||
|  | 		"view": ddeSVGViewElement; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | // editorconfig-checker-disable | ||||||
|  | export interface ddeHTMLAnchorElement extends HTMLAnchorElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLAnchorElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLAreaElement extends HTMLAreaElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLAreaElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLAudioElement extends HTMLAudioElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLAudioElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLBaseElement extends HTMLBaseElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLBaseElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLQuoteElement extends HTMLQuoteElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLQuoteElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLBodyElement extends HTMLBodyElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLBodyElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLBRElement extends HTMLBRElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLBRElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLButtonElement extends HTMLButtonElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLButtonElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLCanvasElement extends HTMLCanvasElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLCanvasElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLTableCaptionElement extends HTMLTableCaptionElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLTableCaptionElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLTableColElement extends HTMLTableColElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLTableColElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLTableColElement extends HTMLTableColElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLTableColElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLDataElement extends HTMLDataElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLDataElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLDataListElement extends HTMLDataListElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLDataListElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLModElement extends HTMLModElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLModElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLDetailsElement extends HTMLDetailsElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLDetailsElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLDialogElement extends HTMLDialogElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLDialogElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLDivElement extends HTMLDivElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLDivElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLDListElement extends HTMLDListElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLDListElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLEmbedElement extends HTMLEmbedElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLEmbedElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLFieldSetElement extends HTMLFieldSetElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLFieldSetElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLFormElement extends HTMLFormElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLFormElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLHeadingElement extends HTMLHeadingElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLHeadingElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLHeadElement extends HTMLHeadElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLHeadElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLHRElement extends HTMLHRElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLHRElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLHtmlElement extends HTMLHtmlElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLHtmlElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLIFrameElement extends HTMLIFrameElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLIFrameElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLImageElement extends HTMLImageElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLImageElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLInputElement extends HTMLInputElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLInputElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLLabelElement extends HTMLLabelElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLLabelElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLLegendElement extends HTMLLegendElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLLegendElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLLIElement extends HTMLLIElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLLIElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLLinkElement extends HTMLLinkElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLLinkElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLMapElement extends HTMLMapElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLMapElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLMenuElement extends HTMLMenuElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLMenuElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLMetaElement extends HTMLMetaElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLMetaElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLMeterElement extends HTMLMeterElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLMeterElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLObjectElement extends HTMLObjectElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLObjectElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLOListElement extends HTMLOListElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLOListElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLOptGroupElement extends HTMLOptGroupElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLOptGroupElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLOptionElement extends HTMLOptionElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLOptionElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLOutputElement extends HTMLOutputElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLOutputElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLParagraphElement extends HTMLParagraphElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLParagraphElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLPictureElement extends HTMLPictureElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLPictureElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLPreElement extends HTMLPreElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLPreElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLProgressElement extends HTMLProgressElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLProgressElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLScriptElement extends HTMLScriptElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLScriptElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLSelectElement extends HTMLSelectElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLSelectElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLSlotElement extends HTMLSlotElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLSlotElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLSourceElement extends HTMLSourceElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLSourceElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLSpanElement extends HTMLSpanElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLSpanElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLStyleElement extends HTMLStyleElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLStyleElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLTableElement extends HTMLTableElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLTableElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLTableSectionElement extends HTMLTableSectionElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLTableSectionElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLTableCellElement extends HTMLTableCellElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLTableCellElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLTemplateElement extends HTMLTemplateElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLTemplateElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLTextAreaElement extends HTMLTextAreaElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLTextAreaElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLTableCellElement extends HTMLTableCellElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLTableCellElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLTimeElement extends HTMLTimeElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLTimeElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLTitleElement extends HTMLTitleElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLTitleElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLTableRowElement extends HTMLTableRowElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLTableRowElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLTrackElement extends HTMLTrackElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLTrackElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLUListElement extends HTMLUListElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLUListElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLVideoElement extends HTMLVideoElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLVideoElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGAElement extends SVGAElement { | ||||||
|  | 	append: ddeAppend<ddeSVGAElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGAnimateElement extends SVGAnimateElement { | ||||||
|  | 	append: ddeAppend<ddeSVGAnimateElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGAnimateMotionElement extends SVGAnimateMotionElement { | ||||||
|  | 	append: ddeAppend<ddeSVGAnimateMotionElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGAnimateTransformElement extends SVGAnimateTransformElement { | ||||||
|  | 	append: ddeAppend<ddeSVGAnimateTransformElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGCircleElement extends SVGCircleElement { | ||||||
|  | 	append: ddeAppend<ddeSVGCircleElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGClipPathElement extends SVGClipPathElement { | ||||||
|  | 	append: ddeAppend<ddeSVGClipPathElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGDefsElement extends SVGDefsElement { | ||||||
|  | 	append: ddeAppend<ddeSVGDefsElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGDescElement extends SVGDescElement { | ||||||
|  | 	append: ddeAppend<ddeSVGDescElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGEllipseElement extends SVGEllipseElement { | ||||||
|  | 	append: ddeAppend<ddeSVGEllipseElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEBlendElement extends SVGFEBlendElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEBlendElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEColorMatrixElement extends SVGFEColorMatrixElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEColorMatrixElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEComponentTransferElement extends SVGFEComponentTransferElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEComponentTransferElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFECompositeElement extends SVGFECompositeElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFECompositeElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEConvolveMatrixElement extends SVGFEConvolveMatrixElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEConvolveMatrixElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEDiffuseLightingElement extends SVGFEDiffuseLightingElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEDiffuseLightingElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEDisplacementMapElement extends SVGFEDisplacementMapElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEDisplacementMapElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEDistantLightElement extends SVGFEDistantLightElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEDistantLightElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEDropShadowElement extends SVGFEDropShadowElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEDropShadowElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEFloodElement extends SVGFEFloodElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEFloodElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEFuncAElement extends SVGFEFuncAElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEFuncAElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEFuncBElement extends SVGFEFuncBElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEFuncBElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEFuncGElement extends SVGFEFuncGElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEFuncGElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEFuncRElement extends SVGFEFuncRElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEFuncRElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEGaussianBlurElement extends SVGFEGaussianBlurElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEGaussianBlurElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEImageElement extends SVGFEImageElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEImageElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEMergeElement extends SVGFEMergeElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEMergeElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEMergeNodeElement extends SVGFEMergeNodeElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEMergeNodeElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEMorphologyElement extends SVGFEMorphologyElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEMorphologyElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEOffsetElement extends SVGFEOffsetElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEOffsetElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEPointLightElement extends SVGFEPointLightElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEPointLightElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFESpecularLightingElement extends SVGFESpecularLightingElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFESpecularLightingElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFESpotLightElement extends SVGFESpotLightElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFESpotLightElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFETileElement extends SVGFETileElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFETileElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFETurbulenceElement extends SVGFETurbulenceElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFETurbulenceElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFilterElement extends SVGFilterElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFilterElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGForeignObjectElement extends SVGForeignObjectElement { | ||||||
|  | 	append: ddeAppend<ddeSVGForeignObjectElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGGElement extends SVGGElement { | ||||||
|  | 	append: ddeAppend<ddeSVGGElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGImageElement extends SVGImageElement { | ||||||
|  | 	append: ddeAppend<ddeSVGImageElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGLineElement extends SVGLineElement { | ||||||
|  | 	append: ddeAppend<ddeSVGLineElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGLinearGradientElement extends SVGLinearGradientElement { | ||||||
|  | 	append: ddeAppend<ddeSVGLinearGradientElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGMarkerElement extends SVGMarkerElement { | ||||||
|  | 	append: ddeAppend<ddeSVGMarkerElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGMaskElement extends SVGMaskElement { | ||||||
|  | 	append: ddeAppend<ddeSVGMaskElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGMetadataElement extends SVGMetadataElement { | ||||||
|  | 	append: ddeAppend<ddeSVGMetadataElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGMPathElement extends SVGMPathElement { | ||||||
|  | 	append: ddeAppend<ddeSVGMPathElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGPathElement extends SVGPathElement { | ||||||
|  | 	append: ddeAppend<ddeSVGPathElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGPatternElement extends SVGPatternElement { | ||||||
|  | 	append: ddeAppend<ddeSVGPatternElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGPolygonElement extends SVGPolygonElement { | ||||||
|  | 	append: ddeAppend<ddeSVGPolygonElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGPolylineElement extends SVGPolylineElement { | ||||||
|  | 	append: ddeAppend<ddeSVGPolylineElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGRadialGradientElement extends SVGRadialGradientElement { | ||||||
|  | 	append: ddeAppend<ddeSVGRadialGradientElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGRectElement extends SVGRectElement { | ||||||
|  | 	append: ddeAppend<ddeSVGRectElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGScriptElement extends SVGScriptElement { | ||||||
|  | 	append: ddeAppend<ddeSVGScriptElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGSetElement extends SVGSetElement { | ||||||
|  | 	append: ddeAppend<ddeSVGSetElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGStopElement extends SVGStopElement { | ||||||
|  | 	append: ddeAppend<ddeSVGStopElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGStyleElement extends SVGStyleElement { | ||||||
|  | 	append: ddeAppend<ddeSVGStyleElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGSVGElement extends SVGSVGElement { | ||||||
|  | 	append: ddeAppend<ddeSVGSVGElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGSwitchElement extends SVGSwitchElement { | ||||||
|  | 	append: ddeAppend<ddeSVGSwitchElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGSymbolElement extends SVGSymbolElement { | ||||||
|  | 	append: ddeAppend<ddeSVGSymbolElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGTextElement extends SVGTextElement { | ||||||
|  | 	append: ddeAppend<ddeSVGTextElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGTextPathElement extends SVGTextPathElement { | ||||||
|  | 	append: ddeAppend<ddeSVGTextPathElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGTitleElement extends SVGTitleElement { | ||||||
|  | 	append: ddeAppend<ddeSVGTitleElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGTSpanElement extends SVGTSpanElement { | ||||||
|  | 	append: ddeAppend<ddeSVGTSpanElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGUseElement extends SVGUseElement { | ||||||
|  | 	append: ddeAppend<ddeSVGUseElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGViewElement extends SVGViewElement { | ||||||
|  | 	append: ddeAppend<ddeSVGViewElement>; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | export { | ||||||
|  | 	dispatchEvent$1 as dispatchEvent, | ||||||
|  | 	el as createElement, | ||||||
|  | 	elNS as createElementNS, | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | export as namespace iife; | ||||||
|  |  | ||||||
|  | export {}; | ||||||
							
								
								
									
										3
									
								
								dist/iife-with-signals.min.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								dist/iife-with-signals.min.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										861
									
								
								dist/iife.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										861
									
								
								dist/iife.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,861 @@ | |||||||
|  | // Generated by dts-bundle-generator v9.5.1 | ||||||
|  |  | ||||||
|  | export interface Signal<V, A> { | ||||||
|  | 	/** The current value of the signal */ | ||||||
|  | 	get(): V; | ||||||
|  | 	/** Set new value of the signal */ | ||||||
|  | 	set(value: V, force?: boolean): V; | ||||||
|  | 	toJSON(): V; | ||||||
|  | 	valueOf(): V; | ||||||
|  | } | ||||||
|  | export type Action<V> = (this: { | ||||||
|  | 	value: V; | ||||||
|  | 	stopPropagation(): void; | ||||||
|  | }, ...a: any[]) => typeof signal._ | void; | ||||||
|  | //type SymbolSignal= Symbol; | ||||||
|  | export type SymbolOnclear = symbol; | ||||||
|  | export type Actions<V> = Record<string | SymbolOnclear, Action<V>>; | ||||||
|  | export type OnListenerOptions = Pick<AddEventListenerOptions, "signal"> & { | ||||||
|  | 	first_time?: boolean; | ||||||
|  | }; | ||||||
|  | export type SElement = Node | Element | DocumentFragment | ddeHTMLElement | ddeSVGElement | ddeDocumentFragment; | ||||||
|  | export interface signal { | ||||||
|  | 	_: Symbol; | ||||||
|  | 	/** | ||||||
|  | 	 * Computations signal. This creates a signal which is computed from other signals. | ||||||
|  | 	 * */ | ||||||
|  | 	<V extends () => any>(computation: V): Signal<ReturnType<V>, {}>; | ||||||
|  | 	/** | ||||||
|  | 	 * Simple example: | ||||||
|  | 	 * ```js | ||||||
|  | 	 * const hello= S("Hello Signal"); | ||||||
|  | 	 * ``` | ||||||
|  | 	 * …simple todo signal: | ||||||
|  | 	 * ```js | ||||||
|  | 	 * const todos= S([], { | ||||||
|  | 	 * 	add(v){ this.value.push(S(v)); }, | ||||||
|  | 	 * 	remove(i){ this.value.splice(i, 1); }, | ||||||
|  | 	 * 	[S.symbols.onclear](){ S.clear(...this.value); }, | ||||||
|  | 	 * }); | ||||||
|  | 	 * ``` | ||||||
|  | 	 * …computed signal: | ||||||
|  | 	 * ```js | ||||||
|  | 	 * const name= S("Jan"); | ||||||
|  | 	 * const surname= S("Andrle"); | ||||||
|  | 	 * const fullname= S(()=> name.get()+" "+surname.get()); | ||||||
|  | 	 * ``` | ||||||
|  | 	 * @param value Initial signal value. Or function computing value from other signals. | ||||||
|  | 	 * @param actions Use to define actions on the signal. Such as add item to the array. | ||||||
|  | 	 *		There is also a reserved function `S.symbol.onclear` which is called when the signal is cleared | ||||||
|  | 	 *		by `S.clear`. | ||||||
|  | 	 * */ | ||||||
|  | 	<V, A extends Actions<V>>(value: V, actions?: A): Signal<V, A>; | ||||||
|  | 	action<S extends Signal<any, Actions<any>>, A extends (S extends Signal<any, infer A> ? A : never), N extends keyof A>(signal: S, name: N, ...params: A[N] extends (...args: infer P) => any ? P : never): void; | ||||||
|  | 	clear(...signals: Signal<any, any>[]): void; | ||||||
|  | 	on<T>(signal: Signal<T, any>, onchange: (a: T) => void, options?: OnListenerOptions): void; | ||||||
|  | 	symbols: { | ||||||
|  | 		//signal: SymbolSignal; | ||||||
|  | 		onclear: SymbolOnclear; | ||||||
|  | 	}; | ||||||
|  | 	/** | ||||||
|  | 	 * Reactive element, which is rendered based on the given signal. | ||||||
|  | 	 * ```js | ||||||
|  | 	 * S.el(signal, value=> value ? el("b", "True") : el("i", "False")); | ||||||
|  | 	 * S.el(listS, list=> list.map(li=> el("li", li))); | ||||||
|  | 	 * ``` | ||||||
|  | 	 * */ | ||||||
|  | 	el<S extends any>(signal: Signal<S, any>, el: (v: S) => SElement | SElement[]): DocumentFragment; | ||||||
|  | 	observedAttributes(custom_element: HTMLElement): Record<string, Signal<string, {}>>; | ||||||
|  | } | ||||||
|  | declare const signal: signal; | ||||||
|  | declare global { | ||||||
|  | 	type ddeSignal<T, A = {}> = Signal<T, A>; | ||||||
|  | 	type ddeAction<V> = Action<V>; | ||||||
|  | 	type ddeActions<V> = Actions<V>; | ||||||
|  | } | ||||||
|  | export type CustomElementTagNameMap = { | ||||||
|  | 	"#text": Text; | ||||||
|  | 	"#comment": Comment; | ||||||
|  | }; | ||||||
|  | export type SupportedElement = HTMLElementTagNameMap[keyof HTMLElementTagNameMap] | SVGElementTagNameMap[keyof SVGElementTagNameMap] | MathMLElementTagNameMap[keyof MathMLElementTagNameMap] | CustomElementTagNameMap[keyof CustomElementTagNameMap]; | ||||||
|  | declare global { | ||||||
|  | 	type ddeComponentAttributes = Record<any, any> | undefined; | ||||||
|  | 	type ddeElementAddon<El extends SupportedElement | DocumentFragment | Node> = (element: El, ...rest: any) => any; | ||||||
|  | 	type ddeString = string | Signal<string, {}>; | ||||||
|  | 	type ddeStringable = ddeString | number | Signal<number, {}>; | ||||||
|  | } | ||||||
|  | export type Host<EL extends SupportedElement> = (...addons: ddeElementAddon<EL>[]) => EL; | ||||||
|  | export type PascalCase = `${Capitalize<string>}${string}`; | ||||||
|  | export type AttrsModified = { | ||||||
|  | 	/** | ||||||
|  | 	 * Use string like in HTML (internally uses `*.setAttribute("style", *)`), or object representation (like DOM API). | ||||||
|  | 	 */ | ||||||
|  | 	style: Partial<CSSStyleDeclaration> | ddeString | Partial<{ | ||||||
|  | 		[K in keyof CSSStyleDeclaration]: Signal<CSSStyleDeclaration[K], {}>; | ||||||
|  | 	}>; | ||||||
|  | 	/** | ||||||
|  | 	 * Provide option to add/remove/toggle CSS clasess (index of object) using 1/0/-1. | ||||||
|  | 	 * In fact `el.classList.toggle(class_name)` for `-1` and `el.classList.toggle(class_name, Boolean(...))` | ||||||
|  | 	 * for others. | ||||||
|  | 	 */ | ||||||
|  | 	classList: Record<string, -1 | 0 | 1 | boolean | Signal<-1 | 0 | 1 | boolean, {}>>; | ||||||
|  | 	/** | ||||||
|  | 	 * Used by the dataset HTML attribute to represent data for custom attributes added to elements. | ||||||
|  | 	 * Values are converted to string (see {@link DOMStringMap}). | ||||||
|  | 	 * | ||||||
|  | 	 * [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMStringMap) | ||||||
|  | 	 * */ | ||||||
|  | 	dataset: Record<string, ddeStringable>; | ||||||
|  | 	/** | ||||||
|  | 	 * Sets `aria-*` simiraly to `dataset` | ||||||
|  | 	 * */ | ||||||
|  | 	ariaset: Record<string, ddeString>; | ||||||
|  | } & Record<`=${string}` | `data${PascalCase}` | `aria${PascalCase}`, ddeString> & Record<`.${string}`, any>; | ||||||
|  | export type _fromElsInterfaces<EL extends SupportedElement> = Omit<EL, keyof AttrsModified>; | ||||||
|  | export type IsReadonly<T, K extends keyof T> = T extends { | ||||||
|  | 	readonly [P in K]: T[K]; | ||||||
|  | } ? true : false; | ||||||
|  | /** | ||||||
|  |  * Just element attributtes | ||||||
|  |  * | ||||||
|  |  * In most cases, you can use native propertie such as | ||||||
|  |  * [MDN WEB/API/Element](https://developer.mozilla.org/en-US/docs/Web/API/Element) and so on | ||||||
|  |  * (e.g. [`Text`](https://developer.mozilla.org/en-US/docs/Web/API/Text)). | ||||||
|  |  * | ||||||
|  |  * There is added support for `data[A-Z].*`/`aria[A-Z].*` to be converted to the kebab-case alternatives. | ||||||
|  |  * @private | ||||||
|  |  */ | ||||||
|  | export type ElementAttributes<T extends SupportedElement> = Partial<{ | ||||||
|  | 	[K in keyof _fromElsInterfaces<T>]: _fromElsInterfaces<T>[K] extends ((...p: any[]) => any) ? _fromElsInterfaces<T>[K] | ((...p: Parameters<_fromElsInterfaces<T>[K]>) => Signal<ReturnType<_fromElsInterfaces<T>[K]>, {}>) : (IsReadonly<_fromElsInterfaces<T>, K> extends false ? _fromElsInterfaces<T>[K] | Signal<_fromElsInterfaces<T>[K], {}> : ddeStringable); | ||||||
|  | } & AttrsModified> & Record<string, any>; | ||||||
|  | export function classListDeclarative<El extends SupportedElement>(element: El, classList: AttrsModified["classList"]): El; | ||||||
|  | export function assign<El extends SupportedElement>(element: El, ...attrs_array: ElementAttributes<El>[]): El; | ||||||
|  | export function assignAttribute<El extends SupportedElement, ATT extends keyof ElementAttributes<El>>(element: El, attr: ATT, value: ElementAttributes<El>[ATT]): ElementAttributes<El>[ATT]; | ||||||
|  | export type ExtendedHTMLElementTagNameMap = HTMLElementTagNameMap & CustomElementTagNameMap; | ||||||
|  | export namespace el { | ||||||
|  | 	/** | ||||||
|  | 	 * Creates a marker comment for elements | ||||||
|  | 	 * | ||||||
|  | 	 * @param attrs - Marker attributes | ||||||
|  | 	 * @param [is_open=false] - Whether the marker is open-ended | ||||||
|  | 	 * @returns Comment node marker | ||||||
|  | 	 */ | ||||||
|  | 	export function mark(attrs: { | ||||||
|  | 		type: "component" | "reactive" | "later"; | ||||||
|  | 		name?: string; | ||||||
|  | 		host?: "this" | "parentElement"; | ||||||
|  | 	}, is_open?: boolean): Comment; | ||||||
|  | } | ||||||
|  | export function chainableAppend<EL extends SupportedElement>(el: EL): EL | ddeHTMLElement; | ||||||
|  | export function el<A extends ddeComponentAttributes, EL extends SupportedElement | ddeDocumentFragment>(component: (attr: A, ...rest: any[]) => EL, attrs?: NoInfer<A>, ...addons: ddeElementAddon<EL>[]): EL extends ddeHTMLElementTagNameMap[keyof ddeHTMLElementTagNameMap] ? EL : (EL extends ddeDocumentFragment ? EL : ddeHTMLElement); | ||||||
|  | export function el<A extends { | ||||||
|  | 	textContent: ddeStringable; | ||||||
|  | }, EL extends SupportedElement | ddeDocumentFragment>(component: (attr: A, ...rest: any[]) => EL, attrs?: NoInfer<A>["textContent"], ...addons: ddeElementAddon<EL>[]): EL extends ddeHTMLElementTagNameMap[keyof ddeHTMLElementTagNameMap] ? EL : (EL extends ddeDocumentFragment ? EL : ddeHTMLElement); | ||||||
|  | export function el<TAG extends keyof ExtendedHTMLElementTagNameMap>(tag_name: TAG, attrs?: ElementAttributes<ExtendedHTMLElementTagNameMap[NoInfer<TAG>]> | ddeStringable, ...addons: ddeElementAddon<ExtendedHTMLElementTagNameMap[NoInfer<TAG>]>[]): TAG extends keyof ddeHTMLElementTagNameMap ? ddeHTMLElementTagNameMap[TAG] : ddeHTMLElement; | ||||||
|  | export function el(tag_name?: "<>"): ddeDocumentFragment; | ||||||
|  | export function el(tag_name: string, attrs?: ElementAttributes<HTMLElement> | ddeStringable, ...addons: ddeElementAddon<HTMLElement>[]): ddeHTMLElement; | ||||||
|  | export function elNS(namespace: "http://www.w3.org/2000/svg"): <TAG extends keyof SVGElementTagNameMap & string, EL extends (TAG extends keyof SVGElementTagNameMap ? SVGElementTagNameMap[TAG] : SVGElement)>(tag_name: TAG, attrs?: ElementAttributes<NoInfer<EL>> | ddeStringable, ...addons: ddeElementAddon<NoInfer<EL>>[]) => TAG extends keyof ddeSVGElementTagNameMap ? ddeSVGElementTagNameMap[TAG] : ddeSVGElement; | ||||||
|  | export function elNS(namespace: "http://www.w3.org/1998/Math/MathML"): <TAG extends keyof MathMLElementTagNameMap & string, EL extends (TAG extends keyof MathMLElementTagNameMap ? MathMLElementTagNameMap[TAG] : MathMLElement)>(tag_name: TAG, attrs?: ddeStringable | Partial<{ | ||||||
|  | 	[key in keyof EL]: EL[key] | Signal<EL[key], {}> | string | number | boolean; | ||||||
|  | }>, ...addons: ddeElementAddon<NoInfer<EL>>[]) => ddeMathMLElement; | ||||||
|  | export function elNS(namespace: string): (tag_name: string, attrs?: string | ddeStringable | Record<string, any>, ...addons: ddeElementAddon<SupportedElement>[]) => SupportedElement; | ||||||
|  | /** Simulate slots for ddeComponents */ | ||||||
|  | export function simulateSlots<EL extends SupportedElement | DocumentFragment>(root: EL): EL; | ||||||
|  | /** | ||||||
|  |  * Simulate slots in Custom Elements without using `shadowRoot`. | ||||||
|  |  * @param el Custom Element root element | ||||||
|  |  * @param body Body of the custom element | ||||||
|  |  * */ | ||||||
|  | export function simulateSlots<EL extends SupportedElement | DocumentFragment>(el: HTMLElement, body: EL): EL; | ||||||
|  | declare function dispatchEvent$1(name: keyof DocumentEventMap | string, host: Host<SupportedElement>): (data?: any) => void; | ||||||
|  | declare function dispatchEvent$1(name: keyof DocumentEventMap | string, options?: EventInit): (element: SupportedElement, data?: any) => void; | ||||||
|  | declare function dispatchEvent$1(name: keyof DocumentEventMap | string, options: EventInit | null, host: Host<SupportedElement>): (data?: any) => void; | ||||||
|  | export interface On { | ||||||
|  | 	/** Listens to the DOM event. See {@link Document.addEventListener} */ | ||||||
|  | 	<Event extends keyof DocumentEventMap, EL extends SupportedElement>(type: Event, listener: (this: EL, ev: DocumentEventMap[Event] & { | ||||||
|  | 		target: EL; | ||||||
|  | 	}) => any, options?: AddEventListenerOptions): ddeElementAddon<EL>; | ||||||
|  | 	<EE extends ddeElementAddon<SupportedElement> = ddeElementAddon<HTMLElement>>(type: string, listener: (this: EE extends ddeElementAddon<infer El> ? El : never, ev: Event | CustomEvent) => any, options?: AddEventListenerOptions): EE; | ||||||
|  | 	/** Listens to the element is connected to the live DOM. In case of custom elements uses [`connectedCallback`](https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_custom_elements#custom_element_lifecycle_callbacks), or {@link MutationObserver} else where */ // editorconfig-checker-disable-line | ||||||
|  | 	connected<EL extends SupportedElement>(listener: (this: EL, event: CustomEvent<NoInfer<EL>>) => any, options?: AddEventListenerOptions): ddeElementAddon<EL>; | ||||||
|  | 	/** Listens to the element is disconnected from the live DOM. In case of custom elements uses [`disconnectedCallback`](https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_custom_elements#custom_element_lifecycle_callbacks), or {@link MutationObserver} else where */ // editorconfig-checker-disable-line | ||||||
|  | 	disconnected<EL extends SupportedElement>(listener: (this: EL, event: CustomEvent<void>) => any, options?: AddEventListenerOptions): ddeElementAddon<EL>; | ||||||
|  | 	/** | ||||||
|  | 	 * Fires after the next tick of the Javascript event loop. | ||||||
|  | 	 * This is handy for example to apply some property depending on the element content: | ||||||
|  | 	 * ```js | ||||||
|  | 	 * const selected= "Z"; | ||||||
|  | 	 * //... | ||||||
|  | 	 * return el("form").append( | ||||||
|  | 	 *		el("select", null, on.defer(e=> e.value=selected)).append( | ||||||
|  | 	 *			el("option", { value: "A", textContent: "A" }), | ||||||
|  | 	 *			//... | ||||||
|  | 	 *			el("option", { value: "Z", textContent: "Z" }), | ||||||
|  | 	 *		), | ||||||
|  | 	 * ); | ||||||
|  | 	 * ``` | ||||||
|  | 	 * */ | ||||||
|  | 	defer<EL extends SupportedElement>(listener: (element: EL) => any): ddeElementAddon<EL>; | ||||||
|  | } | ||||||
|  | export const on: On; | ||||||
|  | export type Scope = { | ||||||
|  | 	scope: Node | Function | Object; | ||||||
|  | 	host: Host<SupportedElement>; | ||||||
|  | 	custom_element: false | HTMLElement; | ||||||
|  | 	prevent: boolean; | ||||||
|  | }; | ||||||
|  | /** Current scope created last time the `el(Function)` was invoke. (Or {@link scope.push}) */ | ||||||
|  | export const scope: { | ||||||
|  | 	current: Scope; | ||||||
|  | 	/** Stops all automatizations. E. g. signals used as attributes in current scope | ||||||
|  | 	 * registers removing these listeners (and clean signal if no other listeners are detected) | ||||||
|  | 	 * on `disconnected` event. */ | ||||||
|  | 	preventDefault<T extends boolean>(prevent: T): T; | ||||||
|  | 	/** | ||||||
|  | 	 * This represents reference to the current host element — `scope.host()`. | ||||||
|  | 	 * It can be also used to register Addon(s) (functions to be called when component is initized) | ||||||
|  | 	 * — `scope.host(on.connected(console.log))`. | ||||||
|  | 	 * */ | ||||||
|  | 	host: Host<SupportedElement>; | ||||||
|  | 	/** | ||||||
|  | 	 * Creates/gets an AbortController that triggers when the element disconnects | ||||||
|  | 	 * */ | ||||||
|  | 	signal: AbortSignal; | ||||||
|  | 	state: Scope[]; | ||||||
|  | 	/** Adds new child scope. All attributes are inherited by default. */ | ||||||
|  | 	push(scope?: Partial<Scope>): ReturnType<Array<Scope>["push"]>; | ||||||
|  | 	/** Adds root scope as a child of the current scope. */ | ||||||
|  | 	pushRoot(): ReturnType<Array<Scope>["push"]>; | ||||||
|  | 	/** Removes last/current child scope. */ | ||||||
|  | 	pop(): ReturnType<Array<Scope>["pop"]>; | ||||||
|  | }; | ||||||
|  | export function customElementRender<EL extends HTMLElement, P extends any = Record<string, string | Signal<string, {}>>>(target: ShadowRoot | EL, render: (props: P) => SupportedElement | DocumentFragment, props?: P | ((el: EL) => P)): EL; | ||||||
|  | export function customElementWithDDE<EL extends (new () => HTMLElement)>(custom_element: EL): EL; | ||||||
|  | export function lifecyclesToEvents<EL extends (new () => HTMLElement)>(custom_element: EL): EL; | ||||||
|  | /** | ||||||
|  |  * This is used primarly for server side rendering. To be sure that all async operations | ||||||
|  |  * are finished before the page is sent to the client. | ||||||
|  |  * ``` | ||||||
|  |  *	// on component | ||||||
|  |  *	function component(){ | ||||||
|  |  *		… | ||||||
|  |  *		queue(fetch(...).then(...)); | ||||||
|  |  *	} | ||||||
|  |  * | ||||||
|  |  * // building the page | ||||||
|  |  * async function build(){ | ||||||
|  |  *		const { component }= await import("./component.js"); | ||||||
|  |  *		document.body.append(el(component)); | ||||||
|  |  *		await queue(); | ||||||
|  |  *		retutn document.body.innerHTML; | ||||||
|  |  *	} | ||||||
|  |  * ``` | ||||||
|  |  * */ | ||||||
|  | export function queue(promise?: Promise<unknown>): Promise<unknown>; | ||||||
|  | /** | ||||||
|  |  * Memoization utility for caching DOM elements to improve performance. | ||||||
|  |  * Used to prevent unnecessary recreation of elements when rendering lists or complex components. | ||||||
|  |  * | ||||||
|  |  * @param key - Unique identifier for the element (usually an ID or unique value) | ||||||
|  |  * @param generator - Function that creates the element | ||||||
|  |  * @returns The cached element if the key exists, otherwise the result of the generator function | ||||||
|  |  * | ||||||
|  |  * @example | ||||||
|  |  * ```ts | ||||||
|  |  * // Within S.el for list rendering | ||||||
|  |  * S.el(itemsSignal, (items, memo) => | ||||||
|  |  *   el("ul").append( | ||||||
|  |  *     ...items.map(item => | ||||||
|  |  *       memo(item.id, () => el(ItemComponent, item)) | ||||||
|  |  *     ) | ||||||
|  |  *   ) | ||||||
|  |  * ) | ||||||
|  |  * ``` | ||||||
|  |  */ | ||||||
|  | export function memo<T>(key: string | number | object, generator: (key: any) => T): T; | ||||||
|  | /** | ||||||
|  |  * Memo namespace containing utility functions for memoization. | ||||||
|  |  */ | ||||||
|  | export namespace memo { | ||||||
|  | 	/** | ||||||
|  | 	 * Checks if an object is a memo scope. | ||||||
|  | 	 * @param obj - The object to check | ||||||
|  | 	 * @returns True if the object is a memo scope | ||||||
|  | 	 */ | ||||||
|  | 	export function isScope(obj: any): boolean; | ||||||
|  | 	/** | ||||||
|  | 	 * Creates a memoized function with optional cleanup support. | ||||||
|  | 	 * | ||||||
|  | 	 * @param fun - The function to memoize | ||||||
|  | 	 * @param options - Configuration options | ||||||
|  | 	 * @param options.signal - AbortSignal for cleanup | ||||||
|  | 	 * @param options.onlyLast - When true, only keeps the cache from the most recent call | ||||||
|  | 	 * @returns A memoized version of the function with a .clear() method | ||||||
|  | 	 * | ||||||
|  | 	 * @example | ||||||
|  | 	 * ```ts | ||||||
|  | 	 * const renderItems = memo.scope(function(items) { | ||||||
|  | 	 *	 return items.map(item => | ||||||
|  | 	 *		 memo(item.id, () => el("div", item.name)) | ||||||
|  | 	 *	 ); | ||||||
|  | 	 * }, { | ||||||
|  | 	 *	 signal: controller.signal, | ||||||
|  | 	 *	 onlyLast: true | ||||||
|  | 	 * }); | ||||||
|  | 	 * ``` | ||||||
|  | 	 */ | ||||||
|  | 	export function scope<F extends Function>(fun: F, options?: { | ||||||
|  | 		signal?: AbortSignal; | ||||||
|  | 		onlyLast?: boolean; | ||||||
|  | 	}): F & { | ||||||
|  | 		clear: () => void; | ||||||
|  | 	}; | ||||||
|  | } | ||||||
|  | /* TypeScript MEH */ | ||||||
|  | declare global { | ||||||
|  | 	type ddeAppend<el> = (...nodes: (Node | string)[]) => el; | ||||||
|  | 	interface ddeDocumentFragment extends DocumentFragment { | ||||||
|  | 		append: ddeAppend<ddeDocumentFragment>; | ||||||
|  | 	} | ||||||
|  | 	interface ddeHTMLElement extends HTMLElement { | ||||||
|  | 		append: ddeAppend<ddeHTMLElement>; | ||||||
|  | 	} | ||||||
|  | 	interface ddeSVGElement extends SVGElement { | ||||||
|  | 		append: ddeAppend<ddeSVGElement>; | ||||||
|  | 	} | ||||||
|  | 	interface ddeMathMLElement extends MathMLElement { | ||||||
|  | 		append: ddeAppend<ddeMathMLElement>; | ||||||
|  | 	} | ||||||
|  | 	interface ddeHTMLElementTagNameMap { | ||||||
|  | 		"a": ddeHTMLAnchorElement; | ||||||
|  | 		"area": ddeHTMLAreaElement; | ||||||
|  | 		"audio": ddeHTMLAudioElement; | ||||||
|  | 		"base": ddeHTMLBaseElement; | ||||||
|  | 		"blockquote": ddeHTMLQuoteElement; | ||||||
|  | 		"body": ddeHTMLBodyElement; | ||||||
|  | 		"br": ddeHTMLBRElement; | ||||||
|  | 		"button": ddeHTMLButtonElement; | ||||||
|  | 		"canvas": ddeHTMLCanvasElement; | ||||||
|  | 		"caption": ddeHTMLTableCaptionElement; | ||||||
|  | 		"col": ddeHTMLTableColElement; | ||||||
|  | 		"colgroup": ddeHTMLTableColElement; | ||||||
|  | 		"data": ddeHTMLDataElement; | ||||||
|  | 		"datalist": ddeHTMLDataListElement; | ||||||
|  | 		"del": ddeHTMLModElement; | ||||||
|  | 		"details": ddeHTMLDetailsElement; | ||||||
|  | 		"dialog": ddeHTMLDialogElement; | ||||||
|  | 		"div": ddeHTMLDivElement; | ||||||
|  | 		"dl": ddeHTMLDListElement; | ||||||
|  | 		"embed": ddeHTMLEmbedElement; | ||||||
|  | 		"fieldset": ddeHTMLFieldSetElement; | ||||||
|  | 		"form": ddeHTMLFormElement; | ||||||
|  | 		"h1": ddeHTMLHeadingElement; | ||||||
|  | 		"h2": ddeHTMLHeadingElement; | ||||||
|  | 		"h3": ddeHTMLHeadingElement; | ||||||
|  | 		"h4": ddeHTMLHeadingElement; | ||||||
|  | 		"h5": ddeHTMLHeadingElement; | ||||||
|  | 		"h6": ddeHTMLHeadingElement; | ||||||
|  | 		"head": ddeHTMLHeadElement; | ||||||
|  | 		"hr": ddeHTMLHRElement; | ||||||
|  | 		"html": ddeHTMLHtmlElement; | ||||||
|  | 		"iframe": ddeHTMLIFrameElement; | ||||||
|  | 		"img": ddeHTMLImageElement; | ||||||
|  | 		"input": ddeHTMLInputElement; | ||||||
|  | 		"ins": ddeHTMLModElement; | ||||||
|  | 		"label": ddeHTMLLabelElement; | ||||||
|  | 		"legend": ddeHTMLLegendElement; | ||||||
|  | 		"li": ddeHTMLLIElement; | ||||||
|  | 		"link": ddeHTMLLinkElement; | ||||||
|  | 		"map": ddeHTMLMapElement; | ||||||
|  | 		"menu": ddeHTMLMenuElement; | ||||||
|  | 		"meta": ddeHTMLMetaElement; | ||||||
|  | 		"meter": ddeHTMLMeterElement; | ||||||
|  | 		"object": ddeHTMLObjectElement; | ||||||
|  | 		"ol": ddeHTMLOListElement; | ||||||
|  | 		"optgroup": ddeHTMLOptGroupElement; | ||||||
|  | 		"option": ddeHTMLOptionElement; | ||||||
|  | 		"output": ddeHTMLOutputElement; | ||||||
|  | 		"p": ddeHTMLParagraphElement; | ||||||
|  | 		"picture": ddeHTMLPictureElement; | ||||||
|  | 		"pre": ddeHTMLPreElement; | ||||||
|  | 		"progress": ddeHTMLProgressElement; | ||||||
|  | 		"q": ddeHTMLQuoteElement; | ||||||
|  | 		"script": ddeHTMLScriptElement; | ||||||
|  | 		"select": ddeHTMLSelectElement; | ||||||
|  | 		"slot": ddeHTMLSlotElement; | ||||||
|  | 		"source": ddeHTMLSourceElement; | ||||||
|  | 		"span": ddeHTMLSpanElement; | ||||||
|  | 		"style": ddeHTMLStyleElement; | ||||||
|  | 		"table": ddeHTMLTableElement; | ||||||
|  | 		"tbody": ddeHTMLTableSectionElement; | ||||||
|  | 		"td": ddeHTMLTableCellElement; | ||||||
|  | 		"template": ddeHTMLTemplateElement; | ||||||
|  | 		"textarea": ddeHTMLTextAreaElement; | ||||||
|  | 		"tfoot": ddeHTMLTableSectionElement; | ||||||
|  | 		"th": ddeHTMLTableCellElement; | ||||||
|  | 		"thead": ddeHTMLTableSectionElement; | ||||||
|  | 		"time": ddeHTMLTimeElement; | ||||||
|  | 		"title": ddeHTMLTitleElement; | ||||||
|  | 		"tr": ddeHTMLTableRowElement; | ||||||
|  | 		"track": ddeHTMLTrackElement; | ||||||
|  | 		"ul": ddeHTMLUListElement; | ||||||
|  | 		"video": ddeHTMLVideoElement; | ||||||
|  | 	} | ||||||
|  | 	interface ddeSVGElementTagNameMap { | ||||||
|  | 		"a": ddeSVGAElement; | ||||||
|  | 		"animate": ddeSVGAnimateElement; | ||||||
|  | 		"animateMotion": ddeSVGAnimateMotionElement; | ||||||
|  | 		"animateTransform": ddeSVGAnimateTransformElement; | ||||||
|  | 		"circle": ddeSVGCircleElement; | ||||||
|  | 		"clipPath": ddeSVGClipPathElement; | ||||||
|  | 		"defs": ddeSVGDefsElement; | ||||||
|  | 		"desc": ddeSVGDescElement; | ||||||
|  | 		"ellipse": ddeSVGEllipseElement; | ||||||
|  | 		"feBlend": ddeSVGFEBlendElement; | ||||||
|  | 		"feColorMatrix": ddeSVGFEColorMatrixElement; | ||||||
|  | 		"feComponentTransfer": ddeSVGFEComponentTransferElement; | ||||||
|  | 		"feComposite": ddeSVGFECompositeElement; | ||||||
|  | 		"feConvolveMatrix": ddeSVGFEConvolveMatrixElement; | ||||||
|  | 		"feDiffuseLighting": ddeSVGFEDiffuseLightingElement; | ||||||
|  | 		"feDisplacementMap": ddeSVGFEDisplacementMapElement; | ||||||
|  | 		"feDistantLight": ddeSVGFEDistantLightElement; | ||||||
|  | 		"feDropShadow": ddeSVGFEDropShadowElement; | ||||||
|  | 		"feFlood": ddeSVGFEFloodElement; | ||||||
|  | 		"feFuncA": ddeSVGFEFuncAElement; | ||||||
|  | 		"feFuncB": ddeSVGFEFuncBElement; | ||||||
|  | 		"feFuncG": ddeSVGFEFuncGElement; | ||||||
|  | 		"feFuncR": ddeSVGFEFuncRElement; | ||||||
|  | 		"feGaussianBlur": ddeSVGFEGaussianBlurElement; | ||||||
|  | 		"feImage": ddeSVGFEImageElement; | ||||||
|  | 		"feMerge": ddeSVGFEMergeElement; | ||||||
|  | 		"feMergeNode": ddeSVGFEMergeNodeElement; | ||||||
|  | 		"feMorphology": ddeSVGFEMorphologyElement; | ||||||
|  | 		"feOffset": ddeSVGFEOffsetElement; | ||||||
|  | 		"fePointLight": ddeSVGFEPointLightElement; | ||||||
|  | 		"feSpecularLighting": ddeSVGFESpecularLightingElement; | ||||||
|  | 		"feSpotLight": ddeSVGFESpotLightElement; | ||||||
|  | 		"feTile": ddeSVGFETileElement; | ||||||
|  | 		"feTurbulence": ddeSVGFETurbulenceElement; | ||||||
|  | 		"filter": ddeSVGFilterElement; | ||||||
|  | 		"foreignObject": ddeSVGForeignObjectElement; | ||||||
|  | 		"g": ddeSVGGElement; | ||||||
|  | 		"image": ddeSVGImageElement; | ||||||
|  | 		"line": ddeSVGLineElement; | ||||||
|  | 		"linearGradient": ddeSVGLinearGradientElement; | ||||||
|  | 		"marker": ddeSVGMarkerElement; | ||||||
|  | 		"mask": ddeSVGMaskElement; | ||||||
|  | 		"metadata": ddeSVGMetadataElement; | ||||||
|  | 		"mpath": ddeSVGMPathElement; | ||||||
|  | 		"path": ddeSVGPathElement; | ||||||
|  | 		"pattern": ddeSVGPatternElement; | ||||||
|  | 		"polygon": ddeSVGPolygonElement; | ||||||
|  | 		"polyline": ddeSVGPolylineElement; | ||||||
|  | 		"radialGradient": ddeSVGRadialGradientElement; | ||||||
|  | 		"rect": ddeSVGRectElement; | ||||||
|  | 		"script": ddeSVGScriptElement; | ||||||
|  | 		"set": ddeSVGSetElement; | ||||||
|  | 		"stop": ddeSVGStopElement; | ||||||
|  | 		"style": ddeSVGStyleElement; | ||||||
|  | 		"svg": ddeSVGSVGElement; | ||||||
|  | 		"switch": ddeSVGSwitchElement; | ||||||
|  | 		"symbol": ddeSVGSymbolElement; | ||||||
|  | 		"text": ddeSVGTextElement; | ||||||
|  | 		"textPath": ddeSVGTextPathElement; | ||||||
|  | 		"title": ddeSVGTitleElement; | ||||||
|  | 		"tspan": ddeSVGTSpanElement; | ||||||
|  | 		"use": ddeSVGUseElement; | ||||||
|  | 		"view": ddeSVGViewElement; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | // editorconfig-checker-disable | ||||||
|  | export interface ddeHTMLAnchorElement extends HTMLAnchorElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLAnchorElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLAreaElement extends HTMLAreaElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLAreaElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLAudioElement extends HTMLAudioElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLAudioElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLBaseElement extends HTMLBaseElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLBaseElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLQuoteElement extends HTMLQuoteElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLQuoteElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLBodyElement extends HTMLBodyElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLBodyElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLBRElement extends HTMLBRElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLBRElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLButtonElement extends HTMLButtonElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLButtonElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLCanvasElement extends HTMLCanvasElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLCanvasElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLTableCaptionElement extends HTMLTableCaptionElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLTableCaptionElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLTableColElement extends HTMLTableColElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLTableColElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLTableColElement extends HTMLTableColElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLTableColElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLDataElement extends HTMLDataElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLDataElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLDataListElement extends HTMLDataListElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLDataListElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLModElement extends HTMLModElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLModElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLDetailsElement extends HTMLDetailsElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLDetailsElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLDialogElement extends HTMLDialogElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLDialogElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLDivElement extends HTMLDivElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLDivElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLDListElement extends HTMLDListElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLDListElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLEmbedElement extends HTMLEmbedElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLEmbedElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLFieldSetElement extends HTMLFieldSetElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLFieldSetElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLFormElement extends HTMLFormElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLFormElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLHeadingElement extends HTMLHeadingElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLHeadingElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLHeadElement extends HTMLHeadElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLHeadElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLHRElement extends HTMLHRElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLHRElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLHtmlElement extends HTMLHtmlElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLHtmlElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLIFrameElement extends HTMLIFrameElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLIFrameElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLImageElement extends HTMLImageElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLImageElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLInputElement extends HTMLInputElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLInputElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLLabelElement extends HTMLLabelElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLLabelElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLLegendElement extends HTMLLegendElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLLegendElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLLIElement extends HTMLLIElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLLIElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLLinkElement extends HTMLLinkElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLLinkElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLMapElement extends HTMLMapElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLMapElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLMenuElement extends HTMLMenuElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLMenuElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLMetaElement extends HTMLMetaElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLMetaElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLMeterElement extends HTMLMeterElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLMeterElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLObjectElement extends HTMLObjectElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLObjectElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLOListElement extends HTMLOListElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLOListElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLOptGroupElement extends HTMLOptGroupElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLOptGroupElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLOptionElement extends HTMLOptionElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLOptionElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLOutputElement extends HTMLOutputElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLOutputElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLParagraphElement extends HTMLParagraphElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLParagraphElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLPictureElement extends HTMLPictureElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLPictureElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLPreElement extends HTMLPreElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLPreElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLProgressElement extends HTMLProgressElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLProgressElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLScriptElement extends HTMLScriptElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLScriptElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLSelectElement extends HTMLSelectElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLSelectElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLSlotElement extends HTMLSlotElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLSlotElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLSourceElement extends HTMLSourceElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLSourceElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLSpanElement extends HTMLSpanElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLSpanElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLStyleElement extends HTMLStyleElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLStyleElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLTableElement extends HTMLTableElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLTableElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLTableSectionElement extends HTMLTableSectionElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLTableSectionElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLTableCellElement extends HTMLTableCellElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLTableCellElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLTemplateElement extends HTMLTemplateElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLTemplateElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLTextAreaElement extends HTMLTextAreaElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLTextAreaElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLTableCellElement extends HTMLTableCellElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLTableCellElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLTimeElement extends HTMLTimeElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLTimeElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLTitleElement extends HTMLTitleElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLTitleElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLTableRowElement extends HTMLTableRowElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLTableRowElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLTrackElement extends HTMLTrackElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLTrackElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLUListElement extends HTMLUListElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLUListElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLVideoElement extends HTMLVideoElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLVideoElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGAElement extends SVGAElement { | ||||||
|  | 	append: ddeAppend<ddeSVGAElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGAnimateElement extends SVGAnimateElement { | ||||||
|  | 	append: ddeAppend<ddeSVGAnimateElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGAnimateMotionElement extends SVGAnimateMotionElement { | ||||||
|  | 	append: ddeAppend<ddeSVGAnimateMotionElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGAnimateTransformElement extends SVGAnimateTransformElement { | ||||||
|  | 	append: ddeAppend<ddeSVGAnimateTransformElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGCircleElement extends SVGCircleElement { | ||||||
|  | 	append: ddeAppend<ddeSVGCircleElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGClipPathElement extends SVGClipPathElement { | ||||||
|  | 	append: ddeAppend<ddeSVGClipPathElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGDefsElement extends SVGDefsElement { | ||||||
|  | 	append: ddeAppend<ddeSVGDefsElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGDescElement extends SVGDescElement { | ||||||
|  | 	append: ddeAppend<ddeSVGDescElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGEllipseElement extends SVGEllipseElement { | ||||||
|  | 	append: ddeAppend<ddeSVGEllipseElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEBlendElement extends SVGFEBlendElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEBlendElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEColorMatrixElement extends SVGFEColorMatrixElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEColorMatrixElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEComponentTransferElement extends SVGFEComponentTransferElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEComponentTransferElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFECompositeElement extends SVGFECompositeElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFECompositeElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEConvolveMatrixElement extends SVGFEConvolveMatrixElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEConvolveMatrixElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEDiffuseLightingElement extends SVGFEDiffuseLightingElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEDiffuseLightingElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEDisplacementMapElement extends SVGFEDisplacementMapElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEDisplacementMapElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEDistantLightElement extends SVGFEDistantLightElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEDistantLightElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEDropShadowElement extends SVGFEDropShadowElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEDropShadowElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEFloodElement extends SVGFEFloodElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEFloodElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEFuncAElement extends SVGFEFuncAElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEFuncAElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEFuncBElement extends SVGFEFuncBElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEFuncBElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEFuncGElement extends SVGFEFuncGElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEFuncGElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEFuncRElement extends SVGFEFuncRElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEFuncRElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEGaussianBlurElement extends SVGFEGaussianBlurElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEGaussianBlurElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEImageElement extends SVGFEImageElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEImageElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEMergeElement extends SVGFEMergeElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEMergeElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEMergeNodeElement extends SVGFEMergeNodeElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEMergeNodeElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEMorphologyElement extends SVGFEMorphologyElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEMorphologyElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEOffsetElement extends SVGFEOffsetElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEOffsetElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEPointLightElement extends SVGFEPointLightElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEPointLightElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFESpecularLightingElement extends SVGFESpecularLightingElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFESpecularLightingElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFESpotLightElement extends SVGFESpotLightElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFESpotLightElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFETileElement extends SVGFETileElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFETileElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFETurbulenceElement extends SVGFETurbulenceElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFETurbulenceElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFilterElement extends SVGFilterElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFilterElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGForeignObjectElement extends SVGForeignObjectElement { | ||||||
|  | 	append: ddeAppend<ddeSVGForeignObjectElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGGElement extends SVGGElement { | ||||||
|  | 	append: ddeAppend<ddeSVGGElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGImageElement extends SVGImageElement { | ||||||
|  | 	append: ddeAppend<ddeSVGImageElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGLineElement extends SVGLineElement { | ||||||
|  | 	append: ddeAppend<ddeSVGLineElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGLinearGradientElement extends SVGLinearGradientElement { | ||||||
|  | 	append: ddeAppend<ddeSVGLinearGradientElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGMarkerElement extends SVGMarkerElement { | ||||||
|  | 	append: ddeAppend<ddeSVGMarkerElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGMaskElement extends SVGMaskElement { | ||||||
|  | 	append: ddeAppend<ddeSVGMaskElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGMetadataElement extends SVGMetadataElement { | ||||||
|  | 	append: ddeAppend<ddeSVGMetadataElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGMPathElement extends SVGMPathElement { | ||||||
|  | 	append: ddeAppend<ddeSVGMPathElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGPathElement extends SVGPathElement { | ||||||
|  | 	append: ddeAppend<ddeSVGPathElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGPatternElement extends SVGPatternElement { | ||||||
|  | 	append: ddeAppend<ddeSVGPatternElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGPolygonElement extends SVGPolygonElement { | ||||||
|  | 	append: ddeAppend<ddeSVGPolygonElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGPolylineElement extends SVGPolylineElement { | ||||||
|  | 	append: ddeAppend<ddeSVGPolylineElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGRadialGradientElement extends SVGRadialGradientElement { | ||||||
|  | 	append: ddeAppend<ddeSVGRadialGradientElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGRectElement extends SVGRectElement { | ||||||
|  | 	append: ddeAppend<ddeSVGRectElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGScriptElement extends SVGScriptElement { | ||||||
|  | 	append: ddeAppend<ddeSVGScriptElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGSetElement extends SVGSetElement { | ||||||
|  | 	append: ddeAppend<ddeSVGSetElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGStopElement extends SVGStopElement { | ||||||
|  | 	append: ddeAppend<ddeSVGStopElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGStyleElement extends SVGStyleElement { | ||||||
|  | 	append: ddeAppend<ddeSVGStyleElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGSVGElement extends SVGSVGElement { | ||||||
|  | 	append: ddeAppend<ddeSVGSVGElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGSwitchElement extends SVGSwitchElement { | ||||||
|  | 	append: ddeAppend<ddeSVGSwitchElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGSymbolElement extends SVGSymbolElement { | ||||||
|  | 	append: ddeAppend<ddeSVGSymbolElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGTextElement extends SVGTextElement { | ||||||
|  | 	append: ddeAppend<ddeSVGTextElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGTextPathElement extends SVGTextPathElement { | ||||||
|  | 	append: ddeAppend<ddeSVGTextPathElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGTitleElement extends SVGTitleElement { | ||||||
|  | 	append: ddeAppend<ddeSVGTitleElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGTSpanElement extends SVGTSpanElement { | ||||||
|  | 	append: ddeAppend<ddeSVGTSpanElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGUseElement extends SVGUseElement { | ||||||
|  | 	append: ddeAppend<ddeSVGUseElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGViewElement extends SVGViewElement { | ||||||
|  | 	append: ddeAppend<ddeSVGViewElement>; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | export { | ||||||
|  | 	dispatchEvent$1 as dispatchEvent, | ||||||
|  | 	el as createElement, | ||||||
|  | 	elNS as createElementNS, | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | export as namespace iife; | ||||||
|  |  | ||||||
|  | export {}; | ||||||
							
								
								
									
										702
									
								
								dist/iife.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										702
									
								
								dist/iife.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,702 @@ | |||||||
|  | var DDE = (() => { | ||||||
|  | 	var __defProp = Object.defineProperty; | ||||||
|  | 	var __getOwnPropDesc = Object.getOwnPropertyDescriptor; | ||||||
|  | 	var __getOwnPropNames = Object.getOwnPropertyNames; | ||||||
|  | 	var __hasOwnProp = Object.prototype.hasOwnProperty; | ||||||
|  | 	var __export = (target, all) => { | ||||||
|  | 		for (var name in all) | ||||||
|  | 			__defProp(target, name, { get: all[name], enumerable: true }); | ||||||
|  | 	}; | ||||||
|  | 	var __copyProps = (to, from, except, desc) => { | ||||||
|  | 		if (from && typeof from === "object" || typeof from === "function") { | ||||||
|  | 			for (let key of __getOwnPropNames(from)) | ||||||
|  | 				if (!__hasOwnProp.call(to, key) && key !== except) | ||||||
|  | 					__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); | ||||||
|  | 		} | ||||||
|  | 		return to; | ||||||
|  | 	}; | ||||||
|  | 	var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); | ||||||
|  |  | ||||||
|  | 	// index.js | ||||||
|  | 	var index_exports = {}; | ||||||
|  | 	__export(index_exports, { | ||||||
|  | 		assign: () => assign, | ||||||
|  | 		assignAttribute: () => assignAttribute, | ||||||
|  | 		chainableAppend: () => chainableAppend, | ||||||
|  | 		classListDeclarative: () => classListDeclarative, | ||||||
|  | 		createElement: () => createElement, | ||||||
|  | 		createElementNS: () => createElementNS, | ||||||
|  | 		customElementRender: () => customElementRender, | ||||||
|  | 		customElementWithDDE: () => lifecyclesToEvents, | ||||||
|  | 		dispatchEvent: () => dispatchEvent, | ||||||
|  | 		el: () => createElement, | ||||||
|  | 		elNS: () => createElementNS, | ||||||
|  | 		lifecyclesToEvents: () => lifecyclesToEvents, | ||||||
|  | 		memo: () => memo, | ||||||
|  | 		on: () => on, | ||||||
|  | 		queue: () => queue, | ||||||
|  | 		registerReactivity: () => registerReactivity, | ||||||
|  | 		scope: () => scope, | ||||||
|  | 		simulateSlots: () => simulateSlots | ||||||
|  | 	}); | ||||||
|  |  | ||||||
|  | 	// src/helpers.js | ||||||
|  | 	var hasOwn = (...a) => Object.prototype.hasOwnProperty.call(...a); | ||||||
|  | 	function isUndef(value) { | ||||||
|  | 		return typeof value === "undefined"; | ||||||
|  | 	} | ||||||
|  | 	function isInstance(obj, cls) { | ||||||
|  | 		return obj instanceof cls; | ||||||
|  | 	} | ||||||
|  | 	function isProtoFrom(obj, cls) { | ||||||
|  | 		return Object.prototype.isPrototypeOf.call(cls, obj); | ||||||
|  | 	} | ||||||
|  | 	function oCreate(proto = null, p = {}) { | ||||||
|  | 		return Object.create(proto, p); | ||||||
|  | 	} | ||||||
|  | 	function oAssign(...o) { | ||||||
|  | 		return Object.assign(...o); | ||||||
|  | 	} | ||||||
|  | 	function onAbort(signal, listener) { | ||||||
|  | 		if (!signal || !isInstance(signal, AbortSignal)) | ||||||
|  | 			return true; | ||||||
|  | 		if (signal.aborted) | ||||||
|  | 			return; | ||||||
|  | 		signal.addEventListener("abort", listener); | ||||||
|  | 		return function cleanUp() { | ||||||
|  | 			signal.removeEventListener("abort", listener); | ||||||
|  | 		}; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// src/dom-lib/common.js | ||||||
|  | 	var enviroment = { | ||||||
|  | 		setDeleteAttr, | ||||||
|  | 		ssr: "", | ||||||
|  | 		D: globalThis.document, | ||||||
|  | 		N: globalThis.Node, | ||||||
|  | 		F: globalThis.DocumentFragment, | ||||||
|  | 		H: globalThis.HTMLElement, | ||||||
|  | 		S: globalThis.SVGElement, | ||||||
|  | 		M: globalThis.MutationObserver, | ||||||
|  | 		q: (p) => p || Promise.resolve() | ||||||
|  | 	}; | ||||||
|  | 	function setDeleteAttr(obj, prop, val) { | ||||||
|  | 		Reflect.set(obj, prop, val); | ||||||
|  | 		if (!isUndef(val)) return; | ||||||
|  | 		Reflect.deleteProperty(obj, prop); | ||||||
|  | 		if (isInstance(obj, enviroment.H) && obj.getAttribute(prop) === "undefined") | ||||||
|  | 			return obj.removeAttribute(prop); | ||||||
|  | 		if (Reflect.get(obj, prop) === "undefined") | ||||||
|  | 			return Reflect.set(obj, prop, ""); | ||||||
|  | 	} | ||||||
|  | 	var keyLTE = "__dde_lifecyclesToEvents"; | ||||||
|  | 	var evc = "dde:connected"; | ||||||
|  | 	var evd = "dde:disconnected"; | ||||||
|  | 	var eva = "dde:attributeChanged"; | ||||||
|  |  | ||||||
|  | 	// src/dom-lib/events-observer.js | ||||||
|  | 	var c_ch_o = enviroment.M ? connectionsChangesObserverConstructor() : new Proxy({}, { | ||||||
|  | 		get() { | ||||||
|  | 			return () => { | ||||||
|  | 			}; | ||||||
|  | 		} | ||||||
|  | 	}); | ||||||
|  | 	function connectionsChangesObserverConstructor() { | ||||||
|  | 		const store = /* @__PURE__ */ new Map(); | ||||||
|  | 		let is_observing = false; | ||||||
|  | 		const observerListener = (stop2) => function(mutations) { | ||||||
|  | 			for (const mutation of mutations) { | ||||||
|  | 				if (mutation.type !== "childList") continue; | ||||||
|  | 				if (observerAdded(mutation.addedNodes, true)) { | ||||||
|  | 					stop2(); | ||||||
|  | 					continue; | ||||||
|  | 				} | ||||||
|  | 				if (observerRemoved(mutation.removedNodes, true)) | ||||||
|  | 					stop2(); | ||||||
|  | 			} | ||||||
|  | 		}; | ||||||
|  | 		const observer = new enviroment.M(observerListener(stop)); | ||||||
|  | 		return { | ||||||
|  | 			/** | ||||||
|  | 			* Creates an observer for a specific element | ||||||
|  | 			* @param {Element} element - Element to observe | ||||||
|  | 			* @returns {Function} Cleanup function | ||||||
|  | 			*/ | ||||||
|  | 			observe(element) { | ||||||
|  | 				const o = new enviroment.M(observerListener(() => { | ||||||
|  | 				})); | ||||||
|  | 				o.observe(element, { childList: true, subtree: true }); | ||||||
|  | 				return () => o.disconnect(); | ||||||
|  | 			}, | ||||||
|  | 			/** | ||||||
|  | 			* Register a connection listener for an element | ||||||
|  | 			* @param {Element} element - Element to watch | ||||||
|  | 			* @param {Function} listener - Callback for connection event | ||||||
|  | 			*/ | ||||||
|  | 			onConnected(element, listener) { | ||||||
|  | 				start(); | ||||||
|  | 				const listeners = getElementStore(element); | ||||||
|  | 				if (listeners.connected.has(listener)) return; | ||||||
|  | 				listeners.connected.add(listener); | ||||||
|  | 				listeners.length_c += 1; | ||||||
|  | 			}, | ||||||
|  | 			/** | ||||||
|  | 			* Unregister a connection listener | ||||||
|  | 			* @param {Element} element - Element being watched | ||||||
|  | 			* @param {Function} listener - Callback to remove | ||||||
|  | 			*/ | ||||||
|  | 			offConnected(element, listener) { | ||||||
|  | 				if (!store.has(element)) return; | ||||||
|  | 				const ls = store.get(element); | ||||||
|  | 				if (!ls.connected.has(listener)) return; | ||||||
|  | 				ls.connected.delete(listener); | ||||||
|  | 				ls.length_c -= 1; | ||||||
|  | 				cleanWhenOff(element, ls); | ||||||
|  | 			}, | ||||||
|  | 			/** | ||||||
|  | 			* Register a disconnection listener for an element | ||||||
|  | 			* @param {Element} element - Element to watch | ||||||
|  | 			* @param {Function} listener - Callback for disconnection event | ||||||
|  | 			*/ | ||||||
|  | 			onDisconnected(element, listener) { | ||||||
|  | 				start(); | ||||||
|  | 				const listeners = getElementStore(element); | ||||||
|  | 				if (listeners.disconnected.has(listener)) return; | ||||||
|  | 				listeners.disconnected.add(listener); | ||||||
|  | 				listeners.length_d += 1; | ||||||
|  | 			}, | ||||||
|  | 			/** | ||||||
|  | 			* Unregister a disconnection listener | ||||||
|  | 			* @param {Element} element - Element being watched | ||||||
|  | 			* @param {Function} listener - Callback to remove | ||||||
|  | 			*/ | ||||||
|  | 			offDisconnected(element, listener) { | ||||||
|  | 				if (!store.has(element)) return; | ||||||
|  | 				const ls = store.get(element); | ||||||
|  | 				ls.disconnected.delete(listener); | ||||||
|  | 				ls.length_d -= 1; | ||||||
|  | 				cleanWhenOff(element, ls); | ||||||
|  | 			} | ||||||
|  | 		}; | ||||||
|  | 		function cleanWhenOff(element, ls) { | ||||||
|  | 			if (ls.length_c || ls.length_d) | ||||||
|  | 				return; | ||||||
|  | 			store.delete(element); | ||||||
|  | 			stop(); | ||||||
|  | 		} | ||||||
|  | 		function getElementStore(element) { | ||||||
|  | 			if (store.has(element)) return store.get(element); | ||||||
|  | 			const out = { | ||||||
|  | 				connected: /* @__PURE__ */ new WeakSet(), | ||||||
|  | 				length_c: 0, | ||||||
|  | 				disconnected: /* @__PURE__ */ new WeakSet(), | ||||||
|  | 				length_d: 0 | ||||||
|  | 			}; | ||||||
|  | 			store.set(element, out); | ||||||
|  | 			return out; | ||||||
|  | 		} | ||||||
|  | 		function start() { | ||||||
|  | 			if (is_observing) return; | ||||||
|  | 			is_observing = true; | ||||||
|  | 			observer.observe(enviroment.D.body, { childList: true, subtree: true }); | ||||||
|  | 		} | ||||||
|  | 		function stop() { | ||||||
|  | 			if (!is_observing || store.size) return; | ||||||
|  | 			is_observing = false; | ||||||
|  | 			observer.disconnect(); | ||||||
|  | 		} | ||||||
|  | 		function requestIdle() { | ||||||
|  | 			return new Promise(function(resolve) { | ||||||
|  | 				(requestIdleCallback || requestAnimationFrame)(resolve); | ||||||
|  | 			}); | ||||||
|  | 		} | ||||||
|  | 		async function collectChildren(element) { | ||||||
|  | 			if (store.size > 30) | ||||||
|  | 				await requestIdle(); | ||||||
|  | 			const out = []; | ||||||
|  | 			if (!isInstance(element, enviroment.N)) return out; | ||||||
|  | 			for (const el of store.keys()) { | ||||||
|  | 				if (el === element || !isInstance(el, enviroment.N)) continue; | ||||||
|  | 				if (element.contains(el)) | ||||||
|  | 					out.push(el); | ||||||
|  | 			} | ||||||
|  | 			return out; | ||||||
|  | 		} | ||||||
|  | 		function observerAdded(addedNodes, is_root) { | ||||||
|  | 			let out = false; | ||||||
|  | 			for (const element of addedNodes) { | ||||||
|  | 				if (is_root) collectChildren(element).then(observerAdded); | ||||||
|  | 				if (!store.has(element)) continue; | ||||||
|  | 				const ls = store.get(element); | ||||||
|  | 				if (!ls.length_c) continue; | ||||||
|  | 				element.dispatchEvent(new Event(evc)); | ||||||
|  | 				ls.connected = /* @__PURE__ */ new WeakSet(); | ||||||
|  | 				ls.length_c = 0; | ||||||
|  | 				if (!ls.length_d) store.delete(element); | ||||||
|  | 				out = true; | ||||||
|  | 			} | ||||||
|  | 			return out; | ||||||
|  | 		} | ||||||
|  | 		function observerRemoved(removedNodes, is_root) { | ||||||
|  | 			let out = false; | ||||||
|  | 			for (const element of removedNodes) { | ||||||
|  | 				if (is_root) collectChildren(element).then(observerRemoved); | ||||||
|  | 				if (!store.has(element)) continue; | ||||||
|  | 				const ls = store.get(element); | ||||||
|  | 				if (!ls.length_d) continue; | ||||||
|  | 				(globalThis.queueMicrotask || setTimeout)(dispatchRemove(element)); | ||||||
|  | 				out = true; | ||||||
|  | 			} | ||||||
|  | 			return out; | ||||||
|  | 		} | ||||||
|  | 		function dispatchRemove(element) { | ||||||
|  | 			return () => { | ||||||
|  | 				if (element.isConnected) return; | ||||||
|  | 				element.dispatchEvent(new Event(evd)); | ||||||
|  | 				store.delete(element); | ||||||
|  | 			}; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// src/dom-lib/events.js | ||||||
|  | 	function dispatchEvent(name, options, host) { | ||||||
|  | 		if (typeof options === "function") { | ||||||
|  | 			host = options; | ||||||
|  | 			options = null; | ||||||
|  | 		} | ||||||
|  | 		if (!options) options = {}; | ||||||
|  | 		return function dispatch(element, ...d) { | ||||||
|  | 			if (host) { | ||||||
|  | 				d.unshift(element); | ||||||
|  | 				element = typeof host === "function" ? host() : host; | ||||||
|  | 			} | ||||||
|  | 			const event = d.length ? new CustomEvent(name, oAssign({ detail: d[0] }, options)) : new Event(name, options); | ||||||
|  | 			return element.dispatchEvent(event); | ||||||
|  | 		}; | ||||||
|  | 	} | ||||||
|  | 	function on(event, listener, options) { | ||||||
|  | 		return function registerElement(element) { | ||||||
|  | 			element.addEventListener(event, listener, options); | ||||||
|  | 			return element; | ||||||
|  | 		}; | ||||||
|  | 	} | ||||||
|  | 	on.defer = (fn) => setTimeout.bind(null, fn, 0); | ||||||
|  | 	var lifeOptions = (obj) => oAssign({}, typeof obj === "object" ? obj : null, { once: true }); | ||||||
|  | 	on.connected = function(listener, options) { | ||||||
|  | 		options = lifeOptions(options); | ||||||
|  | 		return function registerElement(element) { | ||||||
|  | 			element.addEventListener(evc, listener, options); | ||||||
|  | 			if (element[keyLTE]) return element; | ||||||
|  | 			if (element.isConnected) return element.dispatchEvent(new Event(evc)), element; | ||||||
|  | 			const c = onAbort(options.signal, () => c_ch_o.offConnected(element, listener)); | ||||||
|  | 			if (c) c_ch_o.onConnected(element, listener); | ||||||
|  | 			return element; | ||||||
|  | 		}; | ||||||
|  | 	}; | ||||||
|  | 	on.disconnected = function(listener, options) { | ||||||
|  | 		options = lifeOptions(options); | ||||||
|  | 		return function registerElement(element) { | ||||||
|  | 			element.addEventListener(evd, listener, options); | ||||||
|  | 			if (element[keyLTE]) return element; | ||||||
|  | 			const c = onAbort(options.signal, () => c_ch_o.offDisconnected(element, listener)); | ||||||
|  | 			if (c) c_ch_o.onDisconnected(element, listener); | ||||||
|  | 			return element; | ||||||
|  | 		}; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	// src/dom-lib/scopes.js | ||||||
|  | 	var scopes = [{ | ||||||
|  | 		get scope() { | ||||||
|  | 			return enviroment.D.body; | ||||||
|  | 		}, | ||||||
|  | 		host: (c) => c ? c(enviroment.D.body) : enviroment.D.body, | ||||||
|  | 		prevent: true | ||||||
|  | 	}]; | ||||||
|  | 	var store_abort = /* @__PURE__ */ new WeakMap(); | ||||||
|  | 	var scope = { | ||||||
|  | 		/** | ||||||
|  | 		* Gets the current scope | ||||||
|  | 		* @returns {typeof scopes[number]} Current scope context | ||||||
|  | 		*/ | ||||||
|  | 		get current() { | ||||||
|  | 			return scopes[scopes.length - 1]; | ||||||
|  | 		}, | ||||||
|  | 		/** | ||||||
|  | 		* Gets the host element of the current scope | ||||||
|  | 		* @returns {Function} Host accessor function | ||||||
|  | 		*/ | ||||||
|  | 		get host() { | ||||||
|  | 			return this.current.host; | ||||||
|  | 		}, | ||||||
|  | 		/** | ||||||
|  | 		* Creates/gets an AbortController that triggers when the element disconnects | ||||||
|  | 		* */ | ||||||
|  | 		get signal() { | ||||||
|  | 			const { host } = this; | ||||||
|  | 			if (store_abort.has(host)) return store_abort.get(host); | ||||||
|  | 			const a = new AbortController(); | ||||||
|  | 			store_abort.set(host, a); | ||||||
|  | 			host(on.disconnected(() => a.abort())); | ||||||
|  | 			return a.signal; | ||||||
|  | 		}, | ||||||
|  | 		/** | ||||||
|  | 		* Prevents default behavior in the current scope | ||||||
|  | 		* @returns {Object} Current scope context | ||||||
|  | 		*/ | ||||||
|  | 		preventDefault() { | ||||||
|  | 			const { current } = this; | ||||||
|  | 			current.prevent = true; | ||||||
|  | 			return current; | ||||||
|  | 		}, | ||||||
|  | 		/** | ||||||
|  | 		* Gets a copy of the current scope stack | ||||||
|  | 		* @returns {Array} Copy of scope stack | ||||||
|  | 		*/ | ||||||
|  | 		get state() { | ||||||
|  | 			return [...scopes]; | ||||||
|  | 		}, | ||||||
|  | 		/** | ||||||
|  | 		* Pushes a new scope to the stack | ||||||
|  | 		* @param {Object} [s={}] - Scope object to push | ||||||
|  | 		* @returns {number} New length of the scope stack | ||||||
|  | 		*/ | ||||||
|  | 		push(s = {}) { | ||||||
|  | 			return scopes.push(oAssign({}, this.current, { prevent: false }, s)); | ||||||
|  | 		}, | ||||||
|  | 		/** | ||||||
|  | 		* Pushes the root scope to the stack | ||||||
|  | 		* @returns {number} New length of the scope stack | ||||||
|  | 		*/ | ||||||
|  | 		pushRoot() { | ||||||
|  | 			return scopes.push(scopes[0]); | ||||||
|  | 		}, | ||||||
|  | 		/** | ||||||
|  | 		* Pops the current scope from the stack | ||||||
|  | 		* @returns {Object|undefined} Popped scope or undefined if only one scope remains | ||||||
|  | 		*/ | ||||||
|  | 		pop() { | ||||||
|  | 			if (scopes.length === 1) return; | ||||||
|  | 			return scopes.pop(); | ||||||
|  | 		} | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	// src/signals-lib/common.js | ||||||
|  | 	var signals_global = { | ||||||
|  | 		/** | ||||||
|  | 		* Checks if a value is a signal | ||||||
|  | 		* @param {any} attributes - Value to check | ||||||
|  | 		* @returns {boolean} Whether the value is a signal | ||||||
|  | 		*/ | ||||||
|  | 		isSignal(attributes) { | ||||||
|  | 			return false; | ||||||
|  | 		}, | ||||||
|  | 		/** | ||||||
|  | 		* Processes an attribute that might be reactive | ||||||
|  | 		* @param {Element} obj - Element that owns the attribute | ||||||
|  | 		* @param {string} key - Attribute name | ||||||
|  | 		* @param {any} attr - Attribute value | ||||||
|  | 		* @param {Function} set - Function to set the attribute | ||||||
|  | 		* @returns {any} Processed attribute value | ||||||
|  | 		*/ | ||||||
|  | 		processReactiveAttribute(obj, key, attr, set) { | ||||||
|  | 			return attr; | ||||||
|  | 		} | ||||||
|  | 	}; | ||||||
|  | 	function registerReactivity(def, global = true) { | ||||||
|  | 		if (global) return oAssign(signals_global, def); | ||||||
|  | 		Object.setPrototypeOf(def, signals_global); | ||||||
|  | 		return def; | ||||||
|  | 	} | ||||||
|  | 	function signals(_this) { | ||||||
|  | 		return isProtoFrom(_this, signals_global) && _this !== signals_global ? _this : signals_global; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// src/dom-lib/helpers.js | ||||||
|  | 	function setRemove(obj, prop, key, val) { | ||||||
|  | 		return obj[(isUndef(val) ? "remove" : "set") + prop](key, val); | ||||||
|  | 	} | ||||||
|  | 	function setRemoveNS(obj, prop, key, val, ns = null) { | ||||||
|  | 		return obj[(isUndef(val) ? "remove" : "set") + prop + "NS"](ns, key, val); | ||||||
|  | 	} | ||||||
|  | 	function setDelete(obj, key, val) { | ||||||
|  | 		Reflect.set(obj, key, val); | ||||||
|  | 		if (!isUndef(val)) return; | ||||||
|  | 		return Reflect.deleteProperty(obj, key); | ||||||
|  | 	} | ||||||
|  | 	function elementAttribute(element, op, key, value) { | ||||||
|  | 		if (isInstance(element, enviroment.H)) | ||||||
|  | 			return element[op + "Attribute"](key, value); | ||||||
|  | 		return element[op + "AttributeNS"](null, key, value); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// src/dom-lib/el.js | ||||||
|  | 	function queue(promise) { | ||||||
|  | 		return enviroment.q(promise); | ||||||
|  | 	} | ||||||
|  | 	function append(...els) { | ||||||
|  | 		this.appendOriginal(...els); | ||||||
|  | 		return this; | ||||||
|  | 	} | ||||||
|  | 	function chainableAppend(el) { | ||||||
|  | 		if (el.append === append) return el; | ||||||
|  | 		el.appendOriginal = el.append; | ||||||
|  | 		el.append = append; | ||||||
|  | 		return el; | ||||||
|  | 	} | ||||||
|  | 	var namespace; | ||||||
|  | 	function createElement(tag, attributes, ...addons) { | ||||||
|  | 		const s = signals(this); | ||||||
|  | 		let scoped = 0; | ||||||
|  | 		let el, el_host; | ||||||
|  | 		const att_type = typeof attributes; | ||||||
|  | 		if (att_type === "string" || att_type === "number" || s.isSignal(attributes)) | ||||||
|  | 			attributes = { textContent: attributes }; | ||||||
|  | 		switch (true) { | ||||||
|  | 			case typeof tag === "function": { | ||||||
|  | 				scoped = 1; | ||||||
|  | 				const host = (...c) => !c.length ? el_host : (scoped === 1 ? addons.unshift(...c) : c.forEach((c2) => c2(el_host)), void 0); | ||||||
|  | 				scope.push({ scope: tag, host }); | ||||||
|  | 				el = tag(attributes || void 0); | ||||||
|  | 				const is_fragment = isInstance(el, enviroment.F); | ||||||
|  | 				if (el.nodeName === "#comment") break; | ||||||
|  | 				const el_mark = createElement.mark({ | ||||||
|  | 					type: "component", | ||||||
|  | 					name: tag.name, | ||||||
|  | 					host: is_fragment ? "this" : "parentElement" | ||||||
|  | 				}); | ||||||
|  | 				el.prepend(el_mark); | ||||||
|  | 				if (is_fragment) el_host = el_mark; | ||||||
|  | 				break; | ||||||
|  | 			} | ||||||
|  | 			case tag === "#text": | ||||||
|  | 				el = assign.call(this, enviroment.D.createTextNode(""), attributes); | ||||||
|  | 				break; | ||||||
|  | 			case (tag === "<>" || !tag): | ||||||
|  | 				el = assign.call(this, enviroment.D.createDocumentFragment(), attributes); | ||||||
|  | 				break; | ||||||
|  | 			case Boolean(namespace): | ||||||
|  | 				el = assign.call(this, enviroment.D.createElementNS(namespace, tag), attributes); | ||||||
|  | 				break; | ||||||
|  | 			case !el: | ||||||
|  | 				el = assign.call(this, enviroment.D.createElement(tag), attributes); | ||||||
|  | 		} | ||||||
|  | 		chainableAppend(el); | ||||||
|  | 		if (!el_host) el_host = el; | ||||||
|  | 		addons.forEach((c) => c(el_host)); | ||||||
|  | 		if (scoped) scope.pop(); | ||||||
|  | 		scoped = 2; | ||||||
|  | 		return el; | ||||||
|  | 	} | ||||||
|  | 	createElement.mark = function(attrs, is_open = false) { | ||||||
|  | 		attrs = Object.entries(attrs).map(([n, v]) => n + `="${v}"`).join(" "); | ||||||
|  | 		const end = is_open ? "" : "/"; | ||||||
|  | 		const out = enviroment.D.createComment(`<dde:mark ${attrs}${enviroment.ssr}${end}>`); | ||||||
|  | 		if (is_open) out.end = enviroment.D.createComment("</dde:mark>"); | ||||||
|  | 		return out; | ||||||
|  | 	}; | ||||||
|  | 	function createElementNS(ns) { | ||||||
|  | 		const _this = this; | ||||||
|  | 		return function createElementNSCurried(...rest) { | ||||||
|  | 			namespace = ns; | ||||||
|  | 			const el = createElement.call(_this, ...rest); | ||||||
|  | 			namespace = void 0; | ||||||
|  | 			return el; | ||||||
|  | 		}; | ||||||
|  | 	} | ||||||
|  | 	var assign_context = /* @__PURE__ */ new WeakMap(); | ||||||
|  | 	var { setDeleteAttr: setDeleteAttr2 } = enviroment; | ||||||
|  | 	function assign(element, ...attributes) { | ||||||
|  | 		if (!attributes.length) return element; | ||||||
|  | 		assign_context.set(element, assignContext(element, this)); | ||||||
|  | 		for (const [key, value] of Object.entries(oAssign({}, ...attributes))) | ||||||
|  | 			assignAttribute.call(this, element, key, value); | ||||||
|  | 		assign_context.delete(element); | ||||||
|  | 		return element; | ||||||
|  | 	} | ||||||
|  | 	function assignAttribute(element, key, value) { | ||||||
|  | 		const { setRemoveAttr, s } = assignContext(element, this); | ||||||
|  | 		const _this = this; | ||||||
|  | 		value = s.processReactiveAttribute( | ||||||
|  | 			element, | ||||||
|  | 			key, | ||||||
|  | 			value, | ||||||
|  | 			(key2, value2) => assignAttribute.call(_this, element, key2, value2) | ||||||
|  | 		); | ||||||
|  | 		const [k] = key; | ||||||
|  | 		if ("=" === k) return setRemoveAttr(key.slice(1), value); | ||||||
|  | 		if ("." === k) return setDelete(element, key.slice(1), value); | ||||||
|  | 		if (/(aria|data)([A-Z])/.test(key)) { | ||||||
|  | 			key = key.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase(); | ||||||
|  | 			return setRemoveAttr(key, value); | ||||||
|  | 		} | ||||||
|  | 		if ("className" === key) key = "class"; | ||||||
|  | 		switch (key) { | ||||||
|  | 			case "xlink:href": | ||||||
|  | 				return setRemoveAttr(key, value, "http://www.w3.org/1999/xlink"); | ||||||
|  | 			case "textContent": | ||||||
|  | 				return setDeleteAttr2(element, key, value); | ||||||
|  | 			case "style": | ||||||
|  | 				if (typeof value !== "object") break; | ||||||
|  | 			/* falls through */ | ||||||
|  | 			case "dataset": | ||||||
|  | 				return forEachEntries(s, key, element, value, setDelete.bind(null, element[key])); | ||||||
|  | 			case "ariaset": | ||||||
|  | 				return forEachEntries(s, key, element, value, (key2, val) => setRemoveAttr("aria-" + key2, val)); | ||||||
|  | 			case "classList": | ||||||
|  | 				return classListDeclarative.call(_this, element, value); | ||||||
|  | 		} | ||||||
|  | 		return isPropSetter(element, key) ? setDeleteAttr2(element, key, value) : setRemoveAttr(key, value); | ||||||
|  | 	} | ||||||
|  | 	function assignContext(element, _this) { | ||||||
|  | 		if (assign_context.has(element)) return assign_context.get(element); | ||||||
|  | 		const is_svg = isInstance(element, enviroment.S); | ||||||
|  | 		const setRemoveAttr = (is_svg ? setRemoveNS : setRemove).bind(null, element, "Attribute"); | ||||||
|  | 		const s = signals(_this); | ||||||
|  | 		return { setRemoveAttr, s }; | ||||||
|  | 	} | ||||||
|  | 	function classListDeclarative(element, toggle) { | ||||||
|  | 		const s = signals(this); | ||||||
|  | 		forEachEntries( | ||||||
|  | 			s, | ||||||
|  | 			"classList", | ||||||
|  | 			element, | ||||||
|  | 			toggle, | ||||||
|  | 			(class_name, val) => element.classList.toggle(class_name, val === -1 ? void 0 : Boolean(val)) | ||||||
|  | 		); | ||||||
|  | 		return element; | ||||||
|  | 	} | ||||||
|  | 	function isPropSetter(el, key) { | ||||||
|  | 		if (!(key in el)) return false; | ||||||
|  | 		const des = getPropDescriptor(el, key); | ||||||
|  | 		return !isUndef(des.set); | ||||||
|  | 	} | ||||||
|  | 	function getPropDescriptor(p, key) { | ||||||
|  | 		p = Object.getPrototypeOf(p); | ||||||
|  | 		if (!p) return {}; | ||||||
|  | 		const des = Object.getOwnPropertyDescriptor(p, key); | ||||||
|  | 		if (!des) return getPropDescriptor(p, key); | ||||||
|  | 		return des; | ||||||
|  | 	} | ||||||
|  | 	function forEachEntries(s, target, element, obj, cb) { | ||||||
|  | 		const S = String; | ||||||
|  | 		if (typeof obj !== "object" || obj === null) return; | ||||||
|  | 		return Object.entries(obj).forEach(function process([key, val]) { | ||||||
|  | 			if (!key) return; | ||||||
|  | 			key = new S(key); | ||||||
|  | 			key.target = target; | ||||||
|  | 			val = s.processReactiveAttribute(element, key, val, cb); | ||||||
|  | 			cb(key, val); | ||||||
|  | 		}); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// src/dom-lib/customElement.js | ||||||
|  | 	function simulateSlots(element, root = element) { | ||||||
|  | 		const mark_e = "\xB9\u2070", mark_s = "\u2713"; | ||||||
|  | 		const slots = Object.fromEntries( | ||||||
|  | 			Array.from(root.querySelectorAll("slot")).filter((s) => !s.name.endsWith(mark_e)).map((s) => [s.name += mark_e, s]) | ||||||
|  | 		); | ||||||
|  | 		element.append = new Proxy(element.append, { | ||||||
|  | 			apply(orig, _, els) { | ||||||
|  | 				if (els[0] === root) return orig.apply(element, els); | ||||||
|  | 				for (const el of els) { | ||||||
|  | 					const name = (el.slot || "") + mark_e; | ||||||
|  | 					try { | ||||||
|  | 						elementAttribute(el, "remove", "slot"); | ||||||
|  | 					} catch (_error) { | ||||||
|  | 					} | ||||||
|  | 					const slot = slots[name]; | ||||||
|  | 					if (!slot) return; | ||||||
|  | 					if (!slot.name.startsWith(mark_s)) { | ||||||
|  | 						slot.childNodes.forEach((c) => c.remove()); | ||||||
|  | 						slot.name = mark_s + name; | ||||||
|  | 					} | ||||||
|  | 					slot.append(el); | ||||||
|  | 				} | ||||||
|  | 				element.append = orig; | ||||||
|  | 				return element; | ||||||
|  | 			} | ||||||
|  | 		}); | ||||||
|  | 		if (element !== root) { | ||||||
|  | 			const els = Array.from(element.childNodes); | ||||||
|  | 			element.append(...els); | ||||||
|  | 		} | ||||||
|  | 		return root; | ||||||
|  | 	} | ||||||
|  | 	function customElementRender(target, render, props = {}) { | ||||||
|  | 		const custom_element = target.host || target; | ||||||
|  | 		scope.push({ | ||||||
|  | 			scope: custom_element, | ||||||
|  | 			host: (...c) => c.length ? c.forEach((c2) => c2(custom_element)) : custom_element | ||||||
|  | 		}); | ||||||
|  | 		if (typeof props === "function") props = props.call(custom_element, custom_element); | ||||||
|  | 		const is_lte = custom_element[keyLTE]; | ||||||
|  | 		if (!is_lte) lifecyclesToEvents(custom_element); | ||||||
|  | 		const out = render.call(custom_element, props); | ||||||
|  | 		if (!is_lte) custom_element.dispatchEvent(new Event(evc)); | ||||||
|  | 		if (target.nodeType === 11 && typeof target.mode === "string") | ||||||
|  | 			custom_element.addEventListener(evd, c_ch_o.observe(target), { once: true }); | ||||||
|  | 		scope.pop(); | ||||||
|  | 		return target.append(out); | ||||||
|  | 	} | ||||||
|  | 	function lifecyclesToEvents(class_declaration) { | ||||||
|  | 		wrapMethod(class_declaration.prototype, "connectedCallback", function(target, thisArg, detail) { | ||||||
|  | 			target.apply(thisArg, detail); | ||||||
|  | 			thisArg.dispatchEvent(new Event(evc)); | ||||||
|  | 		}); | ||||||
|  | 		wrapMethod(class_declaration.prototype, "disconnectedCallback", function(target, thisArg, detail) { | ||||||
|  | 			target.apply(thisArg, detail); | ||||||
|  | 			(globalThis.queueMicrotask || setTimeout)( | ||||||
|  | 				() => !thisArg.isConnected && thisArg.dispatchEvent(new Event(evd)) | ||||||
|  | 			); | ||||||
|  | 		}); | ||||||
|  | 		wrapMethod(class_declaration.prototype, "attributeChangedCallback", function(target, thisArg, detail) { | ||||||
|  | 			const [attribute, , value] = detail; | ||||||
|  | 			thisArg.dispatchEvent(new CustomEvent(eva, { | ||||||
|  | 				detail: [attribute, value] | ||||||
|  | 			})); | ||||||
|  | 			target.apply(thisArg, detail); | ||||||
|  | 		}); | ||||||
|  | 		class_declaration.prototype[keyLTE] = true; | ||||||
|  | 		return class_declaration; | ||||||
|  | 	} | ||||||
|  | 	function wrapMethod(obj, method, apply) { | ||||||
|  | 		obj[method] = new Proxy(obj[method] || (() => { | ||||||
|  | 		}), { apply }); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// src/memo.js | ||||||
|  | 	var memoMark = "__dde_memo"; | ||||||
|  | 	var memo_scope = []; | ||||||
|  | 	function memo(key, generator) { | ||||||
|  | 		if (!memo_scope.length) return generator(key); | ||||||
|  | 		const k = typeof key === "object" ? JSON.stringify(key) : key; | ||||||
|  | 		const [{ cache, after }] = memo_scope; | ||||||
|  | 		return after(k, hasOwn(cache, k) ? cache[k] : generator(key)); | ||||||
|  | 	} | ||||||
|  | 	memo.isScope = function(obj) { | ||||||
|  | 		return obj[memoMark]; | ||||||
|  | 	}; | ||||||
|  | 	memo.scope = function memoScopeCreate(fun, { signal, onlyLast } = {}) { | ||||||
|  | 		let cache = oCreate(); | ||||||
|  | 		function memoScope(...args) { | ||||||
|  | 			if (signal && signal.aborted) | ||||||
|  | 				return fun.apply(this, args); | ||||||
|  | 			let cache_local = onlyLast ? cache : oCreate(); | ||||||
|  | 			memo_scope.unshift({ | ||||||
|  | 				cache, | ||||||
|  | 				after(key, val) { | ||||||
|  | 					return cache_local[key] = val; | ||||||
|  | 				} | ||||||
|  | 			}); | ||||||
|  | 			const out = fun.apply(this, args); | ||||||
|  | 			memo_scope.shift(); | ||||||
|  | 			cache = cache_local; | ||||||
|  | 			return out; | ||||||
|  | 		} | ||||||
|  | 		memoScope[memoMark] = true; | ||||||
|  | 		memoScope.clear = () => cache = oCreate(); | ||||||
|  | 		if (signal) signal.addEventListener("abort", memoScope.clear); | ||||||
|  | 		return memoScope; | ||||||
|  | 	}; | ||||||
|  | 	return __toCommonJS(index_exports); | ||||||
|  | })(); | ||||||
							
								
								
									
										861
									
								
								dist/iife.min.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										861
									
								
								dist/iife.min.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,861 @@ | |||||||
|  | // Generated by dts-bundle-generator v9.5.1 | ||||||
|  |  | ||||||
|  | export interface Signal<V, A> { | ||||||
|  | 	/** The current value of the signal */ | ||||||
|  | 	get(): V; | ||||||
|  | 	/** Set new value of the signal */ | ||||||
|  | 	set(value: V, force?: boolean): V; | ||||||
|  | 	toJSON(): V; | ||||||
|  | 	valueOf(): V; | ||||||
|  | } | ||||||
|  | export type Action<V> = (this: { | ||||||
|  | 	value: V; | ||||||
|  | 	stopPropagation(): void; | ||||||
|  | }, ...a: any[]) => typeof signal._ | void; | ||||||
|  | //type SymbolSignal= Symbol; | ||||||
|  | export type SymbolOnclear = symbol; | ||||||
|  | export type Actions<V> = Record<string | SymbolOnclear, Action<V>>; | ||||||
|  | export type OnListenerOptions = Pick<AddEventListenerOptions, "signal"> & { | ||||||
|  | 	first_time?: boolean; | ||||||
|  | }; | ||||||
|  | export type SElement = Node | Element | DocumentFragment | ddeHTMLElement | ddeSVGElement | ddeDocumentFragment; | ||||||
|  | export interface signal { | ||||||
|  | 	_: Symbol; | ||||||
|  | 	/** | ||||||
|  | 	 * Computations signal. This creates a signal which is computed from other signals. | ||||||
|  | 	 * */ | ||||||
|  | 	<V extends () => any>(computation: V): Signal<ReturnType<V>, {}>; | ||||||
|  | 	/** | ||||||
|  | 	 * Simple example: | ||||||
|  | 	 * ```js | ||||||
|  | 	 * const hello= S("Hello Signal"); | ||||||
|  | 	 * ``` | ||||||
|  | 	 * …simple todo signal: | ||||||
|  | 	 * ```js | ||||||
|  | 	 * const todos= S([], { | ||||||
|  | 	 * 	add(v){ this.value.push(S(v)); }, | ||||||
|  | 	 * 	remove(i){ this.value.splice(i, 1); }, | ||||||
|  | 	 * 	[S.symbols.onclear](){ S.clear(...this.value); }, | ||||||
|  | 	 * }); | ||||||
|  | 	 * ``` | ||||||
|  | 	 * …computed signal: | ||||||
|  | 	 * ```js | ||||||
|  | 	 * const name= S("Jan"); | ||||||
|  | 	 * const surname= S("Andrle"); | ||||||
|  | 	 * const fullname= S(()=> name.get()+" "+surname.get()); | ||||||
|  | 	 * ``` | ||||||
|  | 	 * @param value Initial signal value. Or function computing value from other signals. | ||||||
|  | 	 * @param actions Use to define actions on the signal. Such as add item to the array. | ||||||
|  | 	 *		There is also a reserved function `S.symbol.onclear` which is called when the signal is cleared | ||||||
|  | 	 *		by `S.clear`. | ||||||
|  | 	 * */ | ||||||
|  | 	<V, A extends Actions<V>>(value: V, actions?: A): Signal<V, A>; | ||||||
|  | 	action<S extends Signal<any, Actions<any>>, A extends (S extends Signal<any, infer A> ? A : never), N extends keyof A>(signal: S, name: N, ...params: A[N] extends (...args: infer P) => any ? P : never): void; | ||||||
|  | 	clear(...signals: Signal<any, any>[]): void; | ||||||
|  | 	on<T>(signal: Signal<T, any>, onchange: (a: T) => void, options?: OnListenerOptions): void; | ||||||
|  | 	symbols: { | ||||||
|  | 		//signal: SymbolSignal; | ||||||
|  | 		onclear: SymbolOnclear; | ||||||
|  | 	}; | ||||||
|  | 	/** | ||||||
|  | 	 * Reactive element, which is rendered based on the given signal. | ||||||
|  | 	 * ```js | ||||||
|  | 	 * S.el(signal, value=> value ? el("b", "True") : el("i", "False")); | ||||||
|  | 	 * S.el(listS, list=> list.map(li=> el("li", li))); | ||||||
|  | 	 * ``` | ||||||
|  | 	 * */ | ||||||
|  | 	el<S extends any>(signal: Signal<S, any>, el: (v: S) => SElement | SElement[]): DocumentFragment; | ||||||
|  | 	observedAttributes(custom_element: HTMLElement): Record<string, Signal<string, {}>>; | ||||||
|  | } | ||||||
|  | declare const signal: signal; | ||||||
|  | declare global { | ||||||
|  | 	type ddeSignal<T, A = {}> = Signal<T, A>; | ||||||
|  | 	type ddeAction<V> = Action<V>; | ||||||
|  | 	type ddeActions<V> = Actions<V>; | ||||||
|  | } | ||||||
|  | export type CustomElementTagNameMap = { | ||||||
|  | 	"#text": Text; | ||||||
|  | 	"#comment": Comment; | ||||||
|  | }; | ||||||
|  | export type SupportedElement = HTMLElementTagNameMap[keyof HTMLElementTagNameMap] | SVGElementTagNameMap[keyof SVGElementTagNameMap] | MathMLElementTagNameMap[keyof MathMLElementTagNameMap] | CustomElementTagNameMap[keyof CustomElementTagNameMap]; | ||||||
|  | declare global { | ||||||
|  | 	type ddeComponentAttributes = Record<any, any> | undefined; | ||||||
|  | 	type ddeElementAddon<El extends SupportedElement | DocumentFragment | Node> = (element: El, ...rest: any) => any; | ||||||
|  | 	type ddeString = string | Signal<string, {}>; | ||||||
|  | 	type ddeStringable = ddeString | number | Signal<number, {}>; | ||||||
|  | } | ||||||
|  | export type Host<EL extends SupportedElement> = (...addons: ddeElementAddon<EL>[]) => EL; | ||||||
|  | export type PascalCase = `${Capitalize<string>}${string}`; | ||||||
|  | export type AttrsModified = { | ||||||
|  | 	/** | ||||||
|  | 	 * Use string like in HTML (internally uses `*.setAttribute("style", *)`), or object representation (like DOM API). | ||||||
|  | 	 */ | ||||||
|  | 	style: Partial<CSSStyleDeclaration> | ddeString | Partial<{ | ||||||
|  | 		[K in keyof CSSStyleDeclaration]: Signal<CSSStyleDeclaration[K], {}>; | ||||||
|  | 	}>; | ||||||
|  | 	/** | ||||||
|  | 	 * Provide option to add/remove/toggle CSS clasess (index of object) using 1/0/-1. | ||||||
|  | 	 * In fact `el.classList.toggle(class_name)` for `-1` and `el.classList.toggle(class_name, Boolean(...))` | ||||||
|  | 	 * for others. | ||||||
|  | 	 */ | ||||||
|  | 	classList: Record<string, -1 | 0 | 1 | boolean | Signal<-1 | 0 | 1 | boolean, {}>>; | ||||||
|  | 	/** | ||||||
|  | 	 * Used by the dataset HTML attribute to represent data for custom attributes added to elements. | ||||||
|  | 	 * Values are converted to string (see {@link DOMStringMap}). | ||||||
|  | 	 * | ||||||
|  | 	 * [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMStringMap) | ||||||
|  | 	 * */ | ||||||
|  | 	dataset: Record<string, ddeStringable>; | ||||||
|  | 	/** | ||||||
|  | 	 * Sets `aria-*` simiraly to `dataset` | ||||||
|  | 	 * */ | ||||||
|  | 	ariaset: Record<string, ddeString>; | ||||||
|  | } & Record<`=${string}` | `data${PascalCase}` | `aria${PascalCase}`, ddeString> & Record<`.${string}`, any>; | ||||||
|  | export type _fromElsInterfaces<EL extends SupportedElement> = Omit<EL, keyof AttrsModified>; | ||||||
|  | export type IsReadonly<T, K extends keyof T> = T extends { | ||||||
|  | 	readonly [P in K]: T[K]; | ||||||
|  | } ? true : false; | ||||||
|  | /** | ||||||
|  |  * Just element attributtes | ||||||
|  |  * | ||||||
|  |  * In most cases, you can use native propertie such as | ||||||
|  |  * [MDN WEB/API/Element](https://developer.mozilla.org/en-US/docs/Web/API/Element) and so on | ||||||
|  |  * (e.g. [`Text`](https://developer.mozilla.org/en-US/docs/Web/API/Text)). | ||||||
|  |  * | ||||||
|  |  * There is added support for `data[A-Z].*`/`aria[A-Z].*` to be converted to the kebab-case alternatives. | ||||||
|  |  * @private | ||||||
|  |  */ | ||||||
|  | export type ElementAttributes<T extends SupportedElement> = Partial<{ | ||||||
|  | 	[K in keyof _fromElsInterfaces<T>]: _fromElsInterfaces<T>[K] extends ((...p: any[]) => any) ? _fromElsInterfaces<T>[K] | ((...p: Parameters<_fromElsInterfaces<T>[K]>) => Signal<ReturnType<_fromElsInterfaces<T>[K]>, {}>) : (IsReadonly<_fromElsInterfaces<T>, K> extends false ? _fromElsInterfaces<T>[K] | Signal<_fromElsInterfaces<T>[K], {}> : ddeStringable); | ||||||
|  | } & AttrsModified> & Record<string, any>; | ||||||
|  | export function classListDeclarative<El extends SupportedElement>(element: El, classList: AttrsModified["classList"]): El; | ||||||
|  | export function assign<El extends SupportedElement>(element: El, ...attrs_array: ElementAttributes<El>[]): El; | ||||||
|  | export function assignAttribute<El extends SupportedElement, ATT extends keyof ElementAttributes<El>>(element: El, attr: ATT, value: ElementAttributes<El>[ATT]): ElementAttributes<El>[ATT]; | ||||||
|  | export type ExtendedHTMLElementTagNameMap = HTMLElementTagNameMap & CustomElementTagNameMap; | ||||||
|  | export namespace el { | ||||||
|  | 	/** | ||||||
|  | 	 * Creates a marker comment for elements | ||||||
|  | 	 * | ||||||
|  | 	 * @param attrs - Marker attributes | ||||||
|  | 	 * @param [is_open=false] - Whether the marker is open-ended | ||||||
|  | 	 * @returns Comment node marker | ||||||
|  | 	 */ | ||||||
|  | 	export function mark(attrs: { | ||||||
|  | 		type: "component" | "reactive" | "later"; | ||||||
|  | 		name?: string; | ||||||
|  | 		host?: "this" | "parentElement"; | ||||||
|  | 	}, is_open?: boolean): Comment; | ||||||
|  | } | ||||||
|  | export function chainableAppend<EL extends SupportedElement>(el: EL): EL | ddeHTMLElement; | ||||||
|  | export function el<A extends ddeComponentAttributes, EL extends SupportedElement | ddeDocumentFragment>(component: (attr: A, ...rest: any[]) => EL, attrs?: NoInfer<A>, ...addons: ddeElementAddon<EL>[]): EL extends ddeHTMLElementTagNameMap[keyof ddeHTMLElementTagNameMap] ? EL : (EL extends ddeDocumentFragment ? EL : ddeHTMLElement); | ||||||
|  | export function el<A extends { | ||||||
|  | 	textContent: ddeStringable; | ||||||
|  | }, EL extends SupportedElement | ddeDocumentFragment>(component: (attr: A, ...rest: any[]) => EL, attrs?: NoInfer<A>["textContent"], ...addons: ddeElementAddon<EL>[]): EL extends ddeHTMLElementTagNameMap[keyof ddeHTMLElementTagNameMap] ? EL : (EL extends ddeDocumentFragment ? EL : ddeHTMLElement); | ||||||
|  | export function el<TAG extends keyof ExtendedHTMLElementTagNameMap>(tag_name: TAG, attrs?: ElementAttributes<ExtendedHTMLElementTagNameMap[NoInfer<TAG>]> | ddeStringable, ...addons: ddeElementAddon<ExtendedHTMLElementTagNameMap[NoInfer<TAG>]>[]): TAG extends keyof ddeHTMLElementTagNameMap ? ddeHTMLElementTagNameMap[TAG] : ddeHTMLElement; | ||||||
|  | export function el(tag_name?: "<>"): ddeDocumentFragment; | ||||||
|  | export function el(tag_name: string, attrs?: ElementAttributes<HTMLElement> | ddeStringable, ...addons: ddeElementAddon<HTMLElement>[]): ddeHTMLElement; | ||||||
|  | export function elNS(namespace: "http://www.w3.org/2000/svg"): <TAG extends keyof SVGElementTagNameMap & string, EL extends (TAG extends keyof SVGElementTagNameMap ? SVGElementTagNameMap[TAG] : SVGElement)>(tag_name: TAG, attrs?: ElementAttributes<NoInfer<EL>> | ddeStringable, ...addons: ddeElementAddon<NoInfer<EL>>[]) => TAG extends keyof ddeSVGElementTagNameMap ? ddeSVGElementTagNameMap[TAG] : ddeSVGElement; | ||||||
|  | export function elNS(namespace: "http://www.w3.org/1998/Math/MathML"): <TAG extends keyof MathMLElementTagNameMap & string, EL extends (TAG extends keyof MathMLElementTagNameMap ? MathMLElementTagNameMap[TAG] : MathMLElement)>(tag_name: TAG, attrs?: ddeStringable | Partial<{ | ||||||
|  | 	[key in keyof EL]: EL[key] | Signal<EL[key], {}> | string | number | boolean; | ||||||
|  | }>, ...addons: ddeElementAddon<NoInfer<EL>>[]) => ddeMathMLElement; | ||||||
|  | export function elNS(namespace: string): (tag_name: string, attrs?: string | ddeStringable | Record<string, any>, ...addons: ddeElementAddon<SupportedElement>[]) => SupportedElement; | ||||||
|  | /** Simulate slots for ddeComponents */ | ||||||
|  | export function simulateSlots<EL extends SupportedElement | DocumentFragment>(root: EL): EL; | ||||||
|  | /** | ||||||
|  |  * Simulate slots in Custom Elements without using `shadowRoot`. | ||||||
|  |  * @param el Custom Element root element | ||||||
|  |  * @param body Body of the custom element | ||||||
|  |  * */ | ||||||
|  | export function simulateSlots<EL extends SupportedElement | DocumentFragment>(el: HTMLElement, body: EL): EL; | ||||||
|  | declare function dispatchEvent$1(name: keyof DocumentEventMap | string, host: Host<SupportedElement>): (data?: any) => void; | ||||||
|  | declare function dispatchEvent$1(name: keyof DocumentEventMap | string, options?: EventInit): (element: SupportedElement, data?: any) => void; | ||||||
|  | declare function dispatchEvent$1(name: keyof DocumentEventMap | string, options: EventInit | null, host: Host<SupportedElement>): (data?: any) => void; | ||||||
|  | export interface On { | ||||||
|  | 	/** Listens to the DOM event. See {@link Document.addEventListener} */ | ||||||
|  | 	<Event extends keyof DocumentEventMap, EL extends SupportedElement>(type: Event, listener: (this: EL, ev: DocumentEventMap[Event] & { | ||||||
|  | 		target: EL; | ||||||
|  | 	}) => any, options?: AddEventListenerOptions): ddeElementAddon<EL>; | ||||||
|  | 	<EE extends ddeElementAddon<SupportedElement> = ddeElementAddon<HTMLElement>>(type: string, listener: (this: EE extends ddeElementAddon<infer El> ? El : never, ev: Event | CustomEvent) => any, options?: AddEventListenerOptions): EE; | ||||||
|  | 	/** Listens to the element is connected to the live DOM. In case of custom elements uses [`connectedCallback`](https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_custom_elements#custom_element_lifecycle_callbacks), or {@link MutationObserver} else where */ // editorconfig-checker-disable-line | ||||||
|  | 	connected<EL extends SupportedElement>(listener: (this: EL, event: CustomEvent<NoInfer<EL>>) => any, options?: AddEventListenerOptions): ddeElementAddon<EL>; | ||||||
|  | 	/** Listens to the element is disconnected from the live DOM. In case of custom elements uses [`disconnectedCallback`](https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_custom_elements#custom_element_lifecycle_callbacks), or {@link MutationObserver} else where */ // editorconfig-checker-disable-line | ||||||
|  | 	disconnected<EL extends SupportedElement>(listener: (this: EL, event: CustomEvent<void>) => any, options?: AddEventListenerOptions): ddeElementAddon<EL>; | ||||||
|  | 	/** | ||||||
|  | 	 * Fires after the next tick of the Javascript event loop. | ||||||
|  | 	 * This is handy for example to apply some property depending on the element content: | ||||||
|  | 	 * ```js | ||||||
|  | 	 * const selected= "Z"; | ||||||
|  | 	 * //... | ||||||
|  | 	 * return el("form").append( | ||||||
|  | 	 *		el("select", null, on.defer(e=> e.value=selected)).append( | ||||||
|  | 	 *			el("option", { value: "A", textContent: "A" }), | ||||||
|  | 	 *			//... | ||||||
|  | 	 *			el("option", { value: "Z", textContent: "Z" }), | ||||||
|  | 	 *		), | ||||||
|  | 	 * ); | ||||||
|  | 	 * ``` | ||||||
|  | 	 * */ | ||||||
|  | 	defer<EL extends SupportedElement>(listener: (element: EL) => any): ddeElementAddon<EL>; | ||||||
|  | } | ||||||
|  | export const on: On; | ||||||
|  | export type Scope = { | ||||||
|  | 	scope: Node | Function | Object; | ||||||
|  | 	host: Host<SupportedElement>; | ||||||
|  | 	custom_element: false | HTMLElement; | ||||||
|  | 	prevent: boolean; | ||||||
|  | }; | ||||||
|  | /** Current scope created last time the `el(Function)` was invoke. (Or {@link scope.push}) */ | ||||||
|  | export const scope: { | ||||||
|  | 	current: Scope; | ||||||
|  | 	/** Stops all automatizations. E. g. signals used as attributes in current scope | ||||||
|  | 	 * registers removing these listeners (and clean signal if no other listeners are detected) | ||||||
|  | 	 * on `disconnected` event. */ | ||||||
|  | 	preventDefault<T extends boolean>(prevent: T): T; | ||||||
|  | 	/** | ||||||
|  | 	 * This represents reference to the current host element — `scope.host()`. | ||||||
|  | 	 * It can be also used to register Addon(s) (functions to be called when component is initized) | ||||||
|  | 	 * — `scope.host(on.connected(console.log))`. | ||||||
|  | 	 * */ | ||||||
|  | 	host: Host<SupportedElement>; | ||||||
|  | 	/** | ||||||
|  | 	 * Creates/gets an AbortController that triggers when the element disconnects | ||||||
|  | 	 * */ | ||||||
|  | 	signal: AbortSignal; | ||||||
|  | 	state: Scope[]; | ||||||
|  | 	/** Adds new child scope. All attributes are inherited by default. */ | ||||||
|  | 	push(scope?: Partial<Scope>): ReturnType<Array<Scope>["push"]>; | ||||||
|  | 	/** Adds root scope as a child of the current scope. */ | ||||||
|  | 	pushRoot(): ReturnType<Array<Scope>["push"]>; | ||||||
|  | 	/** Removes last/current child scope. */ | ||||||
|  | 	pop(): ReturnType<Array<Scope>["pop"]>; | ||||||
|  | }; | ||||||
|  | export function customElementRender<EL extends HTMLElement, P extends any = Record<string, string | Signal<string, {}>>>(target: ShadowRoot | EL, render: (props: P) => SupportedElement | DocumentFragment, props?: P | ((el: EL) => P)): EL; | ||||||
|  | export function customElementWithDDE<EL extends (new () => HTMLElement)>(custom_element: EL): EL; | ||||||
|  | export function lifecyclesToEvents<EL extends (new () => HTMLElement)>(custom_element: EL): EL; | ||||||
|  | /** | ||||||
|  |  * This is used primarly for server side rendering. To be sure that all async operations | ||||||
|  |  * are finished before the page is sent to the client. | ||||||
|  |  * ``` | ||||||
|  |  *	// on component | ||||||
|  |  *	function component(){ | ||||||
|  |  *		… | ||||||
|  |  *		queue(fetch(...).then(...)); | ||||||
|  |  *	} | ||||||
|  |  * | ||||||
|  |  * // building the page | ||||||
|  |  * async function build(){ | ||||||
|  |  *		const { component }= await import("./component.js"); | ||||||
|  |  *		document.body.append(el(component)); | ||||||
|  |  *		await queue(); | ||||||
|  |  *		retutn document.body.innerHTML; | ||||||
|  |  *	} | ||||||
|  |  * ``` | ||||||
|  |  * */ | ||||||
|  | export function queue(promise?: Promise<unknown>): Promise<unknown>; | ||||||
|  | /** | ||||||
|  |  * Memoization utility for caching DOM elements to improve performance. | ||||||
|  |  * Used to prevent unnecessary recreation of elements when rendering lists or complex components. | ||||||
|  |  * | ||||||
|  |  * @param key - Unique identifier for the element (usually an ID or unique value) | ||||||
|  |  * @param generator - Function that creates the element | ||||||
|  |  * @returns The cached element if the key exists, otherwise the result of the generator function | ||||||
|  |  * | ||||||
|  |  * @example | ||||||
|  |  * ```ts | ||||||
|  |  * // Within S.el for list rendering | ||||||
|  |  * S.el(itemsSignal, (items, memo) => | ||||||
|  |  *   el("ul").append( | ||||||
|  |  *     ...items.map(item => | ||||||
|  |  *       memo(item.id, () => el(ItemComponent, item)) | ||||||
|  |  *     ) | ||||||
|  |  *   ) | ||||||
|  |  * ) | ||||||
|  |  * ``` | ||||||
|  |  */ | ||||||
|  | export function memo<T>(key: string | number | object, generator: (key: any) => T): T; | ||||||
|  | /** | ||||||
|  |  * Memo namespace containing utility functions for memoization. | ||||||
|  |  */ | ||||||
|  | export namespace memo { | ||||||
|  | 	/** | ||||||
|  | 	 * Checks if an object is a memo scope. | ||||||
|  | 	 * @param obj - The object to check | ||||||
|  | 	 * @returns True if the object is a memo scope | ||||||
|  | 	 */ | ||||||
|  | 	export function isScope(obj: any): boolean; | ||||||
|  | 	/** | ||||||
|  | 	 * Creates a memoized function with optional cleanup support. | ||||||
|  | 	 * | ||||||
|  | 	 * @param fun - The function to memoize | ||||||
|  | 	 * @param options - Configuration options | ||||||
|  | 	 * @param options.signal - AbortSignal for cleanup | ||||||
|  | 	 * @param options.onlyLast - When true, only keeps the cache from the most recent call | ||||||
|  | 	 * @returns A memoized version of the function with a .clear() method | ||||||
|  | 	 * | ||||||
|  | 	 * @example | ||||||
|  | 	 * ```ts | ||||||
|  | 	 * const renderItems = memo.scope(function(items) { | ||||||
|  | 	 *	 return items.map(item => | ||||||
|  | 	 *		 memo(item.id, () => el("div", item.name)) | ||||||
|  | 	 *	 ); | ||||||
|  | 	 * }, { | ||||||
|  | 	 *	 signal: controller.signal, | ||||||
|  | 	 *	 onlyLast: true | ||||||
|  | 	 * }); | ||||||
|  | 	 * ``` | ||||||
|  | 	 */ | ||||||
|  | 	export function scope<F extends Function>(fun: F, options?: { | ||||||
|  | 		signal?: AbortSignal; | ||||||
|  | 		onlyLast?: boolean; | ||||||
|  | 	}): F & { | ||||||
|  | 		clear: () => void; | ||||||
|  | 	}; | ||||||
|  | } | ||||||
|  | /* TypeScript MEH */ | ||||||
|  | declare global { | ||||||
|  | 	type ddeAppend<el> = (...nodes: (Node | string)[]) => el; | ||||||
|  | 	interface ddeDocumentFragment extends DocumentFragment { | ||||||
|  | 		append: ddeAppend<ddeDocumentFragment>; | ||||||
|  | 	} | ||||||
|  | 	interface ddeHTMLElement extends HTMLElement { | ||||||
|  | 		append: ddeAppend<ddeHTMLElement>; | ||||||
|  | 	} | ||||||
|  | 	interface ddeSVGElement extends SVGElement { | ||||||
|  | 		append: ddeAppend<ddeSVGElement>; | ||||||
|  | 	} | ||||||
|  | 	interface ddeMathMLElement extends MathMLElement { | ||||||
|  | 		append: ddeAppend<ddeMathMLElement>; | ||||||
|  | 	} | ||||||
|  | 	interface ddeHTMLElementTagNameMap { | ||||||
|  | 		"a": ddeHTMLAnchorElement; | ||||||
|  | 		"area": ddeHTMLAreaElement; | ||||||
|  | 		"audio": ddeHTMLAudioElement; | ||||||
|  | 		"base": ddeHTMLBaseElement; | ||||||
|  | 		"blockquote": ddeHTMLQuoteElement; | ||||||
|  | 		"body": ddeHTMLBodyElement; | ||||||
|  | 		"br": ddeHTMLBRElement; | ||||||
|  | 		"button": ddeHTMLButtonElement; | ||||||
|  | 		"canvas": ddeHTMLCanvasElement; | ||||||
|  | 		"caption": ddeHTMLTableCaptionElement; | ||||||
|  | 		"col": ddeHTMLTableColElement; | ||||||
|  | 		"colgroup": ddeHTMLTableColElement; | ||||||
|  | 		"data": ddeHTMLDataElement; | ||||||
|  | 		"datalist": ddeHTMLDataListElement; | ||||||
|  | 		"del": ddeHTMLModElement; | ||||||
|  | 		"details": ddeHTMLDetailsElement; | ||||||
|  | 		"dialog": ddeHTMLDialogElement; | ||||||
|  | 		"div": ddeHTMLDivElement; | ||||||
|  | 		"dl": ddeHTMLDListElement; | ||||||
|  | 		"embed": ddeHTMLEmbedElement; | ||||||
|  | 		"fieldset": ddeHTMLFieldSetElement; | ||||||
|  | 		"form": ddeHTMLFormElement; | ||||||
|  | 		"h1": ddeHTMLHeadingElement; | ||||||
|  | 		"h2": ddeHTMLHeadingElement; | ||||||
|  | 		"h3": ddeHTMLHeadingElement; | ||||||
|  | 		"h4": ddeHTMLHeadingElement; | ||||||
|  | 		"h5": ddeHTMLHeadingElement; | ||||||
|  | 		"h6": ddeHTMLHeadingElement; | ||||||
|  | 		"head": ddeHTMLHeadElement; | ||||||
|  | 		"hr": ddeHTMLHRElement; | ||||||
|  | 		"html": ddeHTMLHtmlElement; | ||||||
|  | 		"iframe": ddeHTMLIFrameElement; | ||||||
|  | 		"img": ddeHTMLImageElement; | ||||||
|  | 		"input": ddeHTMLInputElement; | ||||||
|  | 		"ins": ddeHTMLModElement; | ||||||
|  | 		"label": ddeHTMLLabelElement; | ||||||
|  | 		"legend": ddeHTMLLegendElement; | ||||||
|  | 		"li": ddeHTMLLIElement; | ||||||
|  | 		"link": ddeHTMLLinkElement; | ||||||
|  | 		"map": ddeHTMLMapElement; | ||||||
|  | 		"menu": ddeHTMLMenuElement; | ||||||
|  | 		"meta": ddeHTMLMetaElement; | ||||||
|  | 		"meter": ddeHTMLMeterElement; | ||||||
|  | 		"object": ddeHTMLObjectElement; | ||||||
|  | 		"ol": ddeHTMLOListElement; | ||||||
|  | 		"optgroup": ddeHTMLOptGroupElement; | ||||||
|  | 		"option": ddeHTMLOptionElement; | ||||||
|  | 		"output": ddeHTMLOutputElement; | ||||||
|  | 		"p": ddeHTMLParagraphElement; | ||||||
|  | 		"picture": ddeHTMLPictureElement; | ||||||
|  | 		"pre": ddeHTMLPreElement; | ||||||
|  | 		"progress": ddeHTMLProgressElement; | ||||||
|  | 		"q": ddeHTMLQuoteElement; | ||||||
|  | 		"script": ddeHTMLScriptElement; | ||||||
|  | 		"select": ddeHTMLSelectElement; | ||||||
|  | 		"slot": ddeHTMLSlotElement; | ||||||
|  | 		"source": ddeHTMLSourceElement; | ||||||
|  | 		"span": ddeHTMLSpanElement; | ||||||
|  | 		"style": ddeHTMLStyleElement; | ||||||
|  | 		"table": ddeHTMLTableElement; | ||||||
|  | 		"tbody": ddeHTMLTableSectionElement; | ||||||
|  | 		"td": ddeHTMLTableCellElement; | ||||||
|  | 		"template": ddeHTMLTemplateElement; | ||||||
|  | 		"textarea": ddeHTMLTextAreaElement; | ||||||
|  | 		"tfoot": ddeHTMLTableSectionElement; | ||||||
|  | 		"th": ddeHTMLTableCellElement; | ||||||
|  | 		"thead": ddeHTMLTableSectionElement; | ||||||
|  | 		"time": ddeHTMLTimeElement; | ||||||
|  | 		"title": ddeHTMLTitleElement; | ||||||
|  | 		"tr": ddeHTMLTableRowElement; | ||||||
|  | 		"track": ddeHTMLTrackElement; | ||||||
|  | 		"ul": ddeHTMLUListElement; | ||||||
|  | 		"video": ddeHTMLVideoElement; | ||||||
|  | 	} | ||||||
|  | 	interface ddeSVGElementTagNameMap { | ||||||
|  | 		"a": ddeSVGAElement; | ||||||
|  | 		"animate": ddeSVGAnimateElement; | ||||||
|  | 		"animateMotion": ddeSVGAnimateMotionElement; | ||||||
|  | 		"animateTransform": ddeSVGAnimateTransformElement; | ||||||
|  | 		"circle": ddeSVGCircleElement; | ||||||
|  | 		"clipPath": ddeSVGClipPathElement; | ||||||
|  | 		"defs": ddeSVGDefsElement; | ||||||
|  | 		"desc": ddeSVGDescElement; | ||||||
|  | 		"ellipse": ddeSVGEllipseElement; | ||||||
|  | 		"feBlend": ddeSVGFEBlendElement; | ||||||
|  | 		"feColorMatrix": ddeSVGFEColorMatrixElement; | ||||||
|  | 		"feComponentTransfer": ddeSVGFEComponentTransferElement; | ||||||
|  | 		"feComposite": ddeSVGFECompositeElement; | ||||||
|  | 		"feConvolveMatrix": ddeSVGFEConvolveMatrixElement; | ||||||
|  | 		"feDiffuseLighting": ddeSVGFEDiffuseLightingElement; | ||||||
|  | 		"feDisplacementMap": ddeSVGFEDisplacementMapElement; | ||||||
|  | 		"feDistantLight": ddeSVGFEDistantLightElement; | ||||||
|  | 		"feDropShadow": ddeSVGFEDropShadowElement; | ||||||
|  | 		"feFlood": ddeSVGFEFloodElement; | ||||||
|  | 		"feFuncA": ddeSVGFEFuncAElement; | ||||||
|  | 		"feFuncB": ddeSVGFEFuncBElement; | ||||||
|  | 		"feFuncG": ddeSVGFEFuncGElement; | ||||||
|  | 		"feFuncR": ddeSVGFEFuncRElement; | ||||||
|  | 		"feGaussianBlur": ddeSVGFEGaussianBlurElement; | ||||||
|  | 		"feImage": ddeSVGFEImageElement; | ||||||
|  | 		"feMerge": ddeSVGFEMergeElement; | ||||||
|  | 		"feMergeNode": ddeSVGFEMergeNodeElement; | ||||||
|  | 		"feMorphology": ddeSVGFEMorphologyElement; | ||||||
|  | 		"feOffset": ddeSVGFEOffsetElement; | ||||||
|  | 		"fePointLight": ddeSVGFEPointLightElement; | ||||||
|  | 		"feSpecularLighting": ddeSVGFESpecularLightingElement; | ||||||
|  | 		"feSpotLight": ddeSVGFESpotLightElement; | ||||||
|  | 		"feTile": ddeSVGFETileElement; | ||||||
|  | 		"feTurbulence": ddeSVGFETurbulenceElement; | ||||||
|  | 		"filter": ddeSVGFilterElement; | ||||||
|  | 		"foreignObject": ddeSVGForeignObjectElement; | ||||||
|  | 		"g": ddeSVGGElement; | ||||||
|  | 		"image": ddeSVGImageElement; | ||||||
|  | 		"line": ddeSVGLineElement; | ||||||
|  | 		"linearGradient": ddeSVGLinearGradientElement; | ||||||
|  | 		"marker": ddeSVGMarkerElement; | ||||||
|  | 		"mask": ddeSVGMaskElement; | ||||||
|  | 		"metadata": ddeSVGMetadataElement; | ||||||
|  | 		"mpath": ddeSVGMPathElement; | ||||||
|  | 		"path": ddeSVGPathElement; | ||||||
|  | 		"pattern": ddeSVGPatternElement; | ||||||
|  | 		"polygon": ddeSVGPolygonElement; | ||||||
|  | 		"polyline": ddeSVGPolylineElement; | ||||||
|  | 		"radialGradient": ddeSVGRadialGradientElement; | ||||||
|  | 		"rect": ddeSVGRectElement; | ||||||
|  | 		"script": ddeSVGScriptElement; | ||||||
|  | 		"set": ddeSVGSetElement; | ||||||
|  | 		"stop": ddeSVGStopElement; | ||||||
|  | 		"style": ddeSVGStyleElement; | ||||||
|  | 		"svg": ddeSVGSVGElement; | ||||||
|  | 		"switch": ddeSVGSwitchElement; | ||||||
|  | 		"symbol": ddeSVGSymbolElement; | ||||||
|  | 		"text": ddeSVGTextElement; | ||||||
|  | 		"textPath": ddeSVGTextPathElement; | ||||||
|  | 		"title": ddeSVGTitleElement; | ||||||
|  | 		"tspan": ddeSVGTSpanElement; | ||||||
|  | 		"use": ddeSVGUseElement; | ||||||
|  | 		"view": ddeSVGViewElement; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | // editorconfig-checker-disable | ||||||
|  | export interface ddeHTMLAnchorElement extends HTMLAnchorElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLAnchorElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLAreaElement extends HTMLAreaElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLAreaElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLAudioElement extends HTMLAudioElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLAudioElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLBaseElement extends HTMLBaseElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLBaseElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLQuoteElement extends HTMLQuoteElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLQuoteElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLBodyElement extends HTMLBodyElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLBodyElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLBRElement extends HTMLBRElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLBRElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLButtonElement extends HTMLButtonElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLButtonElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLCanvasElement extends HTMLCanvasElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLCanvasElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLTableCaptionElement extends HTMLTableCaptionElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLTableCaptionElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLTableColElement extends HTMLTableColElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLTableColElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLTableColElement extends HTMLTableColElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLTableColElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLDataElement extends HTMLDataElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLDataElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLDataListElement extends HTMLDataListElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLDataListElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLModElement extends HTMLModElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLModElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLDetailsElement extends HTMLDetailsElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLDetailsElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLDialogElement extends HTMLDialogElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLDialogElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLDivElement extends HTMLDivElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLDivElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLDListElement extends HTMLDListElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLDListElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLEmbedElement extends HTMLEmbedElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLEmbedElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLFieldSetElement extends HTMLFieldSetElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLFieldSetElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLFormElement extends HTMLFormElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLFormElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLHeadingElement extends HTMLHeadingElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLHeadingElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLHeadElement extends HTMLHeadElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLHeadElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLHRElement extends HTMLHRElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLHRElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLHtmlElement extends HTMLHtmlElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLHtmlElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLIFrameElement extends HTMLIFrameElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLIFrameElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLImageElement extends HTMLImageElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLImageElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLInputElement extends HTMLInputElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLInputElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLLabelElement extends HTMLLabelElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLLabelElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLLegendElement extends HTMLLegendElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLLegendElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLLIElement extends HTMLLIElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLLIElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLLinkElement extends HTMLLinkElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLLinkElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLMapElement extends HTMLMapElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLMapElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLMenuElement extends HTMLMenuElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLMenuElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLMetaElement extends HTMLMetaElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLMetaElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLMeterElement extends HTMLMeterElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLMeterElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLObjectElement extends HTMLObjectElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLObjectElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLOListElement extends HTMLOListElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLOListElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLOptGroupElement extends HTMLOptGroupElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLOptGroupElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLOptionElement extends HTMLOptionElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLOptionElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLOutputElement extends HTMLOutputElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLOutputElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLParagraphElement extends HTMLParagraphElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLParagraphElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLPictureElement extends HTMLPictureElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLPictureElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLPreElement extends HTMLPreElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLPreElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLProgressElement extends HTMLProgressElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLProgressElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLScriptElement extends HTMLScriptElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLScriptElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLSelectElement extends HTMLSelectElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLSelectElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLSlotElement extends HTMLSlotElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLSlotElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLSourceElement extends HTMLSourceElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLSourceElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLSpanElement extends HTMLSpanElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLSpanElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLStyleElement extends HTMLStyleElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLStyleElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLTableElement extends HTMLTableElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLTableElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLTableSectionElement extends HTMLTableSectionElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLTableSectionElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLTableCellElement extends HTMLTableCellElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLTableCellElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLTemplateElement extends HTMLTemplateElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLTemplateElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLTextAreaElement extends HTMLTextAreaElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLTextAreaElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLTableCellElement extends HTMLTableCellElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLTableCellElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLTimeElement extends HTMLTimeElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLTimeElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLTitleElement extends HTMLTitleElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLTitleElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLTableRowElement extends HTMLTableRowElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLTableRowElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLTrackElement extends HTMLTrackElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLTrackElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLUListElement extends HTMLUListElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLUListElement>; | ||||||
|  | } | ||||||
|  | export interface ddeHTMLVideoElement extends HTMLVideoElement { | ||||||
|  | 	append: ddeAppend<ddeHTMLVideoElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGAElement extends SVGAElement { | ||||||
|  | 	append: ddeAppend<ddeSVGAElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGAnimateElement extends SVGAnimateElement { | ||||||
|  | 	append: ddeAppend<ddeSVGAnimateElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGAnimateMotionElement extends SVGAnimateMotionElement { | ||||||
|  | 	append: ddeAppend<ddeSVGAnimateMotionElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGAnimateTransformElement extends SVGAnimateTransformElement { | ||||||
|  | 	append: ddeAppend<ddeSVGAnimateTransformElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGCircleElement extends SVGCircleElement { | ||||||
|  | 	append: ddeAppend<ddeSVGCircleElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGClipPathElement extends SVGClipPathElement { | ||||||
|  | 	append: ddeAppend<ddeSVGClipPathElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGDefsElement extends SVGDefsElement { | ||||||
|  | 	append: ddeAppend<ddeSVGDefsElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGDescElement extends SVGDescElement { | ||||||
|  | 	append: ddeAppend<ddeSVGDescElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGEllipseElement extends SVGEllipseElement { | ||||||
|  | 	append: ddeAppend<ddeSVGEllipseElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEBlendElement extends SVGFEBlendElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEBlendElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEColorMatrixElement extends SVGFEColorMatrixElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEColorMatrixElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEComponentTransferElement extends SVGFEComponentTransferElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEComponentTransferElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFECompositeElement extends SVGFECompositeElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFECompositeElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEConvolveMatrixElement extends SVGFEConvolveMatrixElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEConvolveMatrixElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEDiffuseLightingElement extends SVGFEDiffuseLightingElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEDiffuseLightingElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEDisplacementMapElement extends SVGFEDisplacementMapElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEDisplacementMapElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEDistantLightElement extends SVGFEDistantLightElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEDistantLightElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEDropShadowElement extends SVGFEDropShadowElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEDropShadowElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEFloodElement extends SVGFEFloodElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEFloodElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEFuncAElement extends SVGFEFuncAElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEFuncAElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEFuncBElement extends SVGFEFuncBElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEFuncBElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEFuncGElement extends SVGFEFuncGElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEFuncGElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEFuncRElement extends SVGFEFuncRElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEFuncRElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEGaussianBlurElement extends SVGFEGaussianBlurElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEGaussianBlurElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEImageElement extends SVGFEImageElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEImageElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEMergeElement extends SVGFEMergeElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEMergeElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEMergeNodeElement extends SVGFEMergeNodeElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEMergeNodeElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEMorphologyElement extends SVGFEMorphologyElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEMorphologyElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEOffsetElement extends SVGFEOffsetElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEOffsetElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFEPointLightElement extends SVGFEPointLightElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFEPointLightElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFESpecularLightingElement extends SVGFESpecularLightingElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFESpecularLightingElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFESpotLightElement extends SVGFESpotLightElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFESpotLightElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFETileElement extends SVGFETileElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFETileElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFETurbulenceElement extends SVGFETurbulenceElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFETurbulenceElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGFilterElement extends SVGFilterElement { | ||||||
|  | 	append: ddeAppend<ddeSVGFilterElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGForeignObjectElement extends SVGForeignObjectElement { | ||||||
|  | 	append: ddeAppend<ddeSVGForeignObjectElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGGElement extends SVGGElement { | ||||||
|  | 	append: ddeAppend<ddeSVGGElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGImageElement extends SVGImageElement { | ||||||
|  | 	append: ddeAppend<ddeSVGImageElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGLineElement extends SVGLineElement { | ||||||
|  | 	append: ddeAppend<ddeSVGLineElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGLinearGradientElement extends SVGLinearGradientElement { | ||||||
|  | 	append: ddeAppend<ddeSVGLinearGradientElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGMarkerElement extends SVGMarkerElement { | ||||||
|  | 	append: ddeAppend<ddeSVGMarkerElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGMaskElement extends SVGMaskElement { | ||||||
|  | 	append: ddeAppend<ddeSVGMaskElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGMetadataElement extends SVGMetadataElement { | ||||||
|  | 	append: ddeAppend<ddeSVGMetadataElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGMPathElement extends SVGMPathElement { | ||||||
|  | 	append: ddeAppend<ddeSVGMPathElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGPathElement extends SVGPathElement { | ||||||
|  | 	append: ddeAppend<ddeSVGPathElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGPatternElement extends SVGPatternElement { | ||||||
|  | 	append: ddeAppend<ddeSVGPatternElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGPolygonElement extends SVGPolygonElement { | ||||||
|  | 	append: ddeAppend<ddeSVGPolygonElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGPolylineElement extends SVGPolylineElement { | ||||||
|  | 	append: ddeAppend<ddeSVGPolylineElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGRadialGradientElement extends SVGRadialGradientElement { | ||||||
|  | 	append: ddeAppend<ddeSVGRadialGradientElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGRectElement extends SVGRectElement { | ||||||
|  | 	append: ddeAppend<ddeSVGRectElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGScriptElement extends SVGScriptElement { | ||||||
|  | 	append: ddeAppend<ddeSVGScriptElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGSetElement extends SVGSetElement { | ||||||
|  | 	append: ddeAppend<ddeSVGSetElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGStopElement extends SVGStopElement { | ||||||
|  | 	append: ddeAppend<ddeSVGStopElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGStyleElement extends SVGStyleElement { | ||||||
|  | 	append: ddeAppend<ddeSVGStyleElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGSVGElement extends SVGSVGElement { | ||||||
|  | 	append: ddeAppend<ddeSVGSVGElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGSwitchElement extends SVGSwitchElement { | ||||||
|  | 	append: ddeAppend<ddeSVGSwitchElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGSymbolElement extends SVGSymbolElement { | ||||||
|  | 	append: ddeAppend<ddeSVGSymbolElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGTextElement extends SVGTextElement { | ||||||
|  | 	append: ddeAppend<ddeSVGTextElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGTextPathElement extends SVGTextPathElement { | ||||||
|  | 	append: ddeAppend<ddeSVGTextPathElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGTitleElement extends SVGTitleElement { | ||||||
|  | 	append: ddeAppend<ddeSVGTitleElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGTSpanElement extends SVGTSpanElement { | ||||||
|  | 	append: ddeAppend<ddeSVGTSpanElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGUseElement extends SVGUseElement { | ||||||
|  | 	append: ddeAppend<ddeSVGUseElement>; | ||||||
|  | } | ||||||
|  | export interface ddeSVGViewElement extends SVGViewElement { | ||||||
|  | 	append: ddeAppend<ddeSVGViewElement>; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | export { | ||||||
|  | 	dispatchEvent$1 as dispatchEvent, | ||||||
|  | 	el as createElement, | ||||||
|  | 	elNS as createElementNS, | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | export as namespace iife; | ||||||
|  |  | ||||||
|  | export {}; | ||||||
							
								
								
									
										1
									
								
								dist/iife.min.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								dist/iife.min.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								docs/assets/devtools.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								docs/assets/devtools.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 145 KiB | 
							
								
								
									
										60
									
								
								docs/assets/favicon.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								docs/assets/favicon.svg
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,60 @@ | |||||||
|  | <?xml version="1.0" encoding="UTF-8" standalone="no"?> | ||||||
|  | <svg | ||||||
|  |    width="64" | ||||||
|  |    height="64" | ||||||
|  |    viewBox="0 0 64 64" | ||||||
|  |    version="1.1" | ||||||
|  |    id="svg2" | ||||||
|  |    sodipodi:docname="favicon.svg" | ||||||
|  |    xml:space="preserve" | ||||||
|  |    inkscape:version="1.4 (e7c3feb100, 2024-10-09)" | ||||||
|  |    xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" | ||||||
|  |    xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" | ||||||
|  |    xmlns="http://www.w3.org/2000/svg" | ||||||
|  |    xmlns:svg="http://www.w3.org/2000/svg"><defs | ||||||
|  |      id="defs2" /><sodipodi:namedview | ||||||
|  |      id="namedview2" | ||||||
|  |      pagecolor="#ffffff" | ||||||
|  |      bordercolor="#000000" | ||||||
|  |      borderopacity="0.25" | ||||||
|  |      inkscape:showpageshadow="2" | ||||||
|  |      inkscape:pageopacity="0.0" | ||||||
|  |      inkscape:pagecheckerboard="0" | ||||||
|  |      inkscape:deskcolor="#d1d1d1" | ||||||
|  |      inkscape:zoom="9.3249707" | ||||||
|  |      inkscape:cx="38.230683" | ||||||
|  |      inkscape:cy="28.150223" | ||||||
|  |      inkscape:window-width="1278" | ||||||
|  |      inkscape:window-height="1023" | ||||||
|  |      inkscape:window-x="0" | ||||||
|  |      inkscape:window-y="0" | ||||||
|  |      inkscape:window-maximized="0" | ||||||
|  |      inkscape:current-layer="svg2" /><rect | ||||||
|  |      x="0" | ||||||
|  |      y="0" | ||||||
|  |      width="64" | ||||||
|  |      height="64" | ||||||
|  |      rx="10" | ||||||
|  |      fill="#2b2b2b" | ||||||
|  |      id="rect1" /><g | ||||||
|  |      transform="matrix(0.98009485,0,0,1.1964871,0.58334513,-7.2134367)" | ||||||
|  |      id="g2" | ||||||
|  |      style="stroke:#666666"><g | ||||||
|  |        id="g3" | ||||||
|  |        transform="matrix(1.0027126,0,0,0.88864615,3.8540039,4.3371297)" | ||||||
|  |        style="stroke:#666666"><path | ||||||
|  |          d="M 8.880742,11.550781 2.9817709,32 8.880742,52.449219" | ||||||
|  |          stroke="#ff5252" | ||||||
|  |          stroke-width="4.25375" | ||||||
|  |          fill="none" | ||||||
|  |          id="path1" | ||||||
|  |          style="stroke:#666666" /><path | ||||||
|  |          d="M 47.330923,11.568743 53.261141,32 47.330923,52.431257" | ||||||
|  |          stroke="#ff5252" | ||||||
|  |          stroke-width="4.26309" | ||||||
|  |          fill="none" | ||||||
|  |          id="path2" | ||||||
|  |          style="stroke:#666666" /></g></g><path | ||||||
|  |      d="m 11.726038,32.656946 q 0,-2.685867 0.823088,-4.721927 0.823088,-2.036061 2.166022,-3.404987 1.342933,-1.360261 3.07575,-2.053387 1.732818,-0.693128 3.552275,-0.693128 4.505325,0 6.844629,2.659875 2.339303,2.668539 2.339303,7.780349 0,0.519846 -0.01733,1.083011 -0.02599,0.563166 -0.06931,0.90973 H 17.227733 q 0,1.992739 1.646176,3.145062 1.646176,1.14366 4.245402,1.14366 1.602856,0 3.058423,-0.346564 1.446902,-0.346563 2.443272,-0.693127 l 0.736447,4.548646 q -1.386253,0.476525 -2.945789,0.797097 -1.559536,0.329235 -3.508954,0.329235 -2.599226,0 -4.652615,-0.675799 -2.062053,-0.667135 -3.508955,-1.984075 -1.455566,-1.325605 -2.235335,-3.275025 -0.779767,-1.94942 -0.779767,-4.548646 m 13.645936,-2.1227 q 0,-0.823088 -0.216602,-1.585528 -0.216602,-0.753776 -0.693127,-1.360263 -0.476525,-0.606485 -1.212973,-0.979042 -0.736447,-0.363891 -1.819457,-0.363891 -1.039691,0 -1.793467,0.346563 -0.762439,0.346564 -1.264955,0.95305 -0.493854,0.606485 -0.771105,1.386253 -0.285915,0.77977 -0.372555,1.602856 z m 26.901988,11.263311 q -0.129961,0.08664 -0.589158,0.303244 -0.450533,0.216602 -1.18698,0.459196 -0.736448,0.23393 -1.793466,0.407211 -1.065682,0.173282 -2.408616,0.173282 -3.682236,0 -5.371734,-2.192014 -1.689496,-2.18335 -1.689496,-6.385432 V 17.278193 H 33.602856 V 12.85951 h 10.960069 v 22.093419 q 0,2.079381 0.823089,2.815829 0.823088,0.736447 2.07938,0.736447 1.602856,0 2.685867,-0.433204 1.08301,-0.433205 1.429574,-0.563166 z" | ||||||
|  |      id="path1-1" | ||||||
|  |      style="fill:#ff5252;stroke-width:0.866409" /></svg> | ||||||
| After Width: | Height: | Size: 3.3 KiB | 
							
								
								
									
										92
									
								
								docs/assets/logo.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										92
									
								
								docs/assets/logo.svg
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,92 @@ | |||||||
|  | <?xml version="1.0" encoding="UTF-8" standalone="no"?> | ||||||
|  | <svg | ||||||
|  |    width="256" | ||||||
|  |    height="256" | ||||||
|  |    viewBox="0 0 256 256" | ||||||
|  |    version="1.1" | ||||||
|  |    id="svg5" | ||||||
|  |    xml:space="preserve" | ||||||
|  |    sodipodi:docname="logo.svg" | ||||||
|  |    inkscape:version="1.4 (e7c3feb100, 2024-10-09)" | ||||||
|  |    xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" | ||||||
|  |    xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" | ||||||
|  |    xmlns="http://www.w3.org/2000/svg" | ||||||
|  |    xmlns:svg="http://www.w3.org/2000/svg"><sodipodi:namedview | ||||||
|  |      id="namedview1" | ||||||
|  |      pagecolor="#ffffff" | ||||||
|  |      bordercolor="#000000" | ||||||
|  |      borderopacity="0.25" | ||||||
|  |      inkscape:showpageshadow="2" | ||||||
|  |      inkscape:pageopacity="0.0" | ||||||
|  |      inkscape:pagecheckerboard="0" | ||||||
|  |      inkscape:deskcolor="#d1d1d1" | ||||||
|  |      inkscape:zoom="3.296875" | ||||||
|  |      inkscape:cx="128" | ||||||
|  |      inkscape:cy="101.61137" | ||||||
|  |      inkscape:window-width="1920" | ||||||
|  |      inkscape:window-height="1052" | ||||||
|  |      inkscape:window-x="0" | ||||||
|  |      inkscape:window-y="0" | ||||||
|  |      inkscape:window-maximized="1" | ||||||
|  |      inkscape:current-layer="g2" /><defs | ||||||
|  |      id="defs4"><linearGradient | ||||||
|  |        id="bgGradient" | ||||||
|  |        x1="18" | ||||||
|  |        y1="18" | ||||||
|  |        x2="238" | ||||||
|  |        y2="238" | ||||||
|  |        gradientUnits="userSpaceOnUse" | ||||||
|  |        gradientTransform="matrix(1.1363636,0,0,1.1363636,-17.454544,-17.454544)"><stop | ||||||
|  |          offset="0" | ||||||
|  |          stop-color="#3b3b3b" | ||||||
|  |          id="stop1" /><stop | ||||||
|  |          offset="1" | ||||||
|  |          stop-color="#2b2b2b" | ||||||
|  |          id="stop2" /></linearGradient><filter | ||||||
|  |        id="glow" | ||||||
|  |        x="-0.089563958" | ||||||
|  |        y="-0.082460006" | ||||||
|  |        width="1.1791279" | ||||||
|  |        height="1.16492"><feGaussianBlur | ||||||
|  |          stdDeviation="4" | ||||||
|  |          result="blur" | ||||||
|  |          id="feGaussianBlur4" | ||||||
|  |          in="SourceGraphic" /><feComposite | ||||||
|  |          in="SourceGraphic" | ||||||
|  |          in2="blur" | ||||||
|  |          operator="over" | ||||||
|  |          id="feComposite4" | ||||||
|  |          result="composite-0" /></filter></defs><rect | ||||||
|  |      x="3" | ||||||
|  |      y="3" | ||||||
|  |      width="250" | ||||||
|  |      height="250" | ||||||
|  |      fill="url(#bgGradient)" | ||||||
|  |      id="rect4" | ||||||
|  |      style="fill:url(#bgGradient);stroke-width:1.13636" | ||||||
|  |      ry="50" /><g | ||||||
|  |      id="g2" | ||||||
|  |      transform="translate(0.4430186,-1.5165883)"><g | ||||||
|  |        id="g1" | ||||||
|  |        transform="matrix(1.5900346,0,0,1.5900346,-121.12651,-66.626074)"><g | ||||||
|  |          opacity="0.25" | ||||||
|  |          fill="#ffffff" | ||||||
|  |          filter="url(#glow)" | ||||||
|  |          id="g5" | ||||||
|  |          transform="matrix(0.55415879,0,0,0.56134669,112.16444,51.505106)"><path | ||||||
|  |            d="m 80,60 -30,68 30,68" | ||||||
|  |            stroke="#ffffff" | ||||||
|  |            stroke-width="8" | ||||||
|  |            fill="none" | ||||||
|  |            id="path4" /><path | ||||||
|  |            d="m 176,60 30,68 -30,68" | ||||||
|  |            stroke="#ffffff" | ||||||
|  |            stroke-width="8" | ||||||
|  |            fill="none" | ||||||
|  |            id="path5" /></g><path | ||||||
|  |          d="m 152.28246,124.58038 q 0,-4.06854 1.24681,-7.15275 1.24681,-3.08421 3.28107,-5.15785 2.03427,-2.06051 4.65913,-3.11046 2.62486,-1.04994 5.38096,-1.04994 6.82464,0 10.3682,4.02916 3.54356,4.04228 3.54356,11.78562 0,0.78746 -0.0263,1.64054 -0.0394,0.85308 -0.10499,1.37805 h -20.01456 q 0,3.01859 2.49362,4.76412 2.49362,1.73241 6.43091,1.73241 2.42799,0 4.63287,-0.52497 2.19176,-0.52497 3.70106,-1.04995 l 1.11556,6.89026 q -2.09989,0.72184 -4.46226,1.20744 -2.36237,0.49872 -5.31534,0.49872 -3.93729,0 -7.04775,-1.02369 -3.12359,-1.01058 -5.31534,-3.00547 -2.20489,-2.00802 -3.38607,-4.96098 -1.18114,-2.95297 -1.18114,-6.89026 m 20.67077,-3.21546 q 0,-1.2468 -0.3281,-2.40174 -0.32811,-1.14182 -1.04995,-2.06052 -0.72183,-0.9187 -1.8374,-1.48304 -1.11557,-0.55123 -2.7561,-0.55123 -1.57492,0 -2.71673,0.52498 -1.15494,0.52497 -1.91615,1.44367 -0.74809,0.9187 -1.16806,2.09989 -0.43311,1.18119 -0.56435,2.42799 z m 40.75096,17.06159 q -0.19687,0.13125 -0.89245,0.45936 -0.68247,0.3281 -1.79803,0.69558 -1.11557,0.35436 -2.71673,0.61685 -1.61429,0.26248 -3.64856,0.26248 -5.57783,0 -8.13707,-3.32045 -2.55923,-3.30732 -2.55923,-9.67261 v -26.18298 h -8.5308 v -6.693389 h 16.60224 v 33.466969 q 0,3.14983 1.24681,4.26539 1.24681,1.11557 3.14983,1.11557 2.428,0 4.06853,-0.65621 1.64054,-0.65622 2.16551,-0.85308 z" | ||||||
|  |          id="path1-3" | ||||||
|  |          style="fill:#ff5252;stroke-width:1.31243" /></g><path | ||||||
|  |        d="m 25.256467,130.12148 q 0,6.64555 2.489444,10.86495 2.468347,4.21939 7.953563,4.21939 1.582274,0 2.953578,-0.10548 1.371303,-0.10549 2.848092,-0.31646 v -27.00413 q -1.476789,-0.84388 -3.375517,-1.4346 -1.898728,-0.56962 -4.008427,-0.56962 -4.641336,0 -6.751034,3.69197 -2.109699,3.69198 -2.109699,10.65398 m 29.219322,23.62862 q -3.586487,1.16034 -8.755248,1.89873 -5.168761,0.7384 -10.126552,0.7384 -11.603341,0 -17.55269,-6.85651 -5.970447,-6.85652 -5.970447,-18.77632 0,-12.13076 5.021083,-19.15606 4.999985,-7.0042 14.810082,-7.0042 2.637123,0 5.168761,0.56962 2.531638,0.59072 4.430366,1.64557 V 84.235539 l 12.974645,-2.215183 z m 23.523136,-23.62862 q 0,6.64555 2.489444,10.86495 2.468344,4.21939 7.953559,4.21939 1.582268,0 2.953578,-0.10548 1.3713,-0.10549 2.84809,-0.31646 v -27.00413 q -1.47679,-0.84388 -3.37552,-1.4346 -1.89873,-0.56962 -4.008423,-0.56962 -4.64133,0 -6.75103,3.69197 -2.109698,3.69198 -2.109698,10.65398 m 29.219315,23.62862 q -3.58648,1.16034 -8.75524,1.89873 -5.168774,0.7384 -10.126562,0.7384 -11.603332,0 -17.552681,-6.85651 -5.970446,-6.85652 -5.970446,-18.77632 0,-12.13076 4.999984,-19.15606 5.021082,-7.0042 14.831178,-7.0042 2.63712,0 5.168753,0.56962 2.53164,0.59072 4.43037,1.64557 V 84.235539 l 12.974644,-2.215183 z" | ||||||
|  |        id="path1" | ||||||
|  |        style="fill:#ff5252;fill-opacity:0.664797;stroke-width:2.1097" /></g></svg> | ||||||
| After Width: | Height: | Size: 5.3 KiB | 
| @@ -1,12 +0,0 @@ | |||||||
| const highlighter= await globalThis.shiki.getHighlighter({ |  | ||||||
| 	theme: "css-variables", |  | ||||||
| 	langs: ["js", "ts", "css", "html", "shell"], |  | ||||||
| }); |  | ||||||
| const codeBlocks= document.querySelectorAll('code[class*="language-"]'); |  | ||||||
|  |  | ||||||
| codeBlocks.forEach((block)=> { |  | ||||||
| 	const lang= block.className.replace("language-", ""); |  | ||||||
| 	block.parentElement.dataset.js= "done"; |  | ||||||
| 	const html= highlighter.codeToHtml(block.textContent, { lang }); |  | ||||||
| 	block.innerHTML= html; |  | ||||||
| }); |  | ||||||
							
								
								
									
										231
									
								
								docs/components/code.html.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										231
									
								
								docs/components/code.html.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,231 @@ | |||||||
|  | import { registerClientFile, styles } from "../ssr.js"; | ||||||
|  | const host= "."+code.name; | ||||||
|  | styles.css` | ||||||
|  | /* Code block styling */ | ||||||
|  | ${host} { | ||||||
|  | 	/* Theme for dark mode - matches Flems/CodeMirror dark theme */ | ||||||
|  | 	--shiki-color-text: #f8f8f2; | ||||||
|  | 	--shiki-color-background: var(--code-bg); | ||||||
|  | 	--shiki-token-constant: #82b1ff; | ||||||
|  | 	--shiki-token-string: #c3e88d; | ||||||
|  | 	--shiki-token-comment: #546e7a; | ||||||
|  | 	--shiki-token-keyword: #c792ea; | ||||||
|  | 	--shiki-token-parameter: #fd971f; | ||||||
|  | 	--shiki-token-function: #80cbae; | ||||||
|  | 	--shiki-token-string-expression: #c3e88d; | ||||||
|  | 	--shiki-token-punctuation: #89ddff; | ||||||
|  | 	--shiki-token-link: #82aaff; | ||||||
|  | 	--shiki-token-variable: #f8f8f2; | ||||||
|  | 	--shiki-token-number: #f78c6c; | ||||||
|  | 	--shiki-token-boolean: #82b1ff; | ||||||
|  | 	--shiki-token-tag: #f07178; | ||||||
|  | 	--shiki-token-attribute: #ffcb6b; | ||||||
|  | 	--shiki-token-property: #82b1ff; | ||||||
|  | 	--shiki-token-operator: #89ddff; | ||||||
|  | 	--shiki-token-regex: #c3e88d; | ||||||
|  | 	--shiki-token-class: #ffcb6b; | ||||||
|  |  | ||||||
|  | 	/* Basic styling */ | ||||||
|  | 	white-space: pre; | ||||||
|  | 	tab-size: 2; | ||||||
|  | 	overflow: auto; | ||||||
|  | 	border-radius: var(--border-radius); | ||||||
|  | 	font-family: var(--font-mono); | ||||||
|  | 	font-size: .85rem; | ||||||
|  | 	line-height: 1.5; | ||||||
|  | 	position: relative; | ||||||
|  | 	margin-block: 1rem; | ||||||
|  | 	max-width: 100%; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* Light mode overrides to match GitHub-like theme */ | ||||||
|  | @media (prefers-color-scheme: light) { | ||||||
|  | 	${host} { | ||||||
|  | 		--shiki-color-text: #24292e; | ||||||
|  | 		--shiki-color-background: var(--code-bg); | ||||||
|  | 		--shiki-token-constant: #005cc5; | ||||||
|  | 		--shiki-token-string: #22863a; | ||||||
|  | 		--shiki-token-comment: #6a737d; | ||||||
|  | 		--shiki-token-keyword: #d73a49; | ||||||
|  | 		--shiki-token-parameter: #e36209; | ||||||
|  | 		--shiki-token-function: #6f42c1; | ||||||
|  | 		--shiki-token-string-expression: #22863a; | ||||||
|  | 		--shiki-token-punctuation: #24292e; | ||||||
|  | 		--shiki-token-link: #0366d6; | ||||||
|  | 		--shiki-token-variable: #24292e; | ||||||
|  | 		--shiki-token-number: #005cc5; | ||||||
|  | 		--shiki-token-boolean: #005cc5; | ||||||
|  | 		--shiki-token-tag: #22863a; | ||||||
|  | 		--shiki-token-attribute: #005cc5; | ||||||
|  | 		--shiki-token-property: #005cc5; | ||||||
|  | 		--shiki-token-operator: #d73a49; | ||||||
|  | 		--shiki-token-regex: #032f62; | ||||||
|  | 		--shiki-token-class: #6f42c1; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* Support for theme toggles */ | ||||||
|  | html[data-theme="light"] ${host} { | ||||||
|  | 	--shiki-color-text: #24292e; | ||||||
|  | 	--shiki-color-background: var(--code-bg); | ||||||
|  | 	--shiki-token-constant: #005cc5; | ||||||
|  | 	--shiki-token-string: #22863a; | ||||||
|  | 	--shiki-token-comment: #6a737d; | ||||||
|  | 	--shiki-token-keyword: #d73a49; | ||||||
|  | 	--shiki-token-parameter: #e36209; | ||||||
|  | 	--shiki-token-function: #6f42c1; | ||||||
|  | 	--shiki-token-string-expression: #22863a; | ||||||
|  | 	--shiki-token-punctuation: #24292e; | ||||||
|  | 	--shiki-token-link: #0366d6; | ||||||
|  | 	--shiki-token-variable: #24292e; | ||||||
|  | 	--shiki-token-number: #005cc5; | ||||||
|  | 	--shiki-token-boolean: #005cc5; | ||||||
|  | 	--shiki-token-tag: #22863a; | ||||||
|  | 	--shiki-token-attribute: #005cc5; | ||||||
|  | 	--shiki-token-property: #005cc5; | ||||||
|  | 	--shiki-token-operator: #d73a49; | ||||||
|  | 	--shiki-token-regex: #032f62; | ||||||
|  | 	--shiki-token-class: #6f42c1; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | html[data-theme="dark"] ${host} { | ||||||
|  | 	--shiki-color-text: #f8f8f2; | ||||||
|  | 	--shiki-color-background: var(--code-bg); | ||||||
|  | 	--shiki-token-constant: #82b1ff; | ||||||
|  | 	--shiki-token-string: #c3e88d; | ||||||
|  | 	--shiki-token-comment: #546e7a; | ||||||
|  | 	--shiki-token-keyword: #c792ea; | ||||||
|  | 	--shiki-token-parameter: #fd971f; | ||||||
|  | 	--shiki-token-function: #80cbae; | ||||||
|  | 	--shiki-token-string-expression: #c3e88d; | ||||||
|  | 	--shiki-token-punctuation: #89ddff; | ||||||
|  | 	--shiki-token-link: #82aaff; | ||||||
|  | 	--shiki-token-variable: #f8f8f2; | ||||||
|  | 	--shiki-token-number: #f78c6c; | ||||||
|  | 	--shiki-token-boolean: #82b1ff; | ||||||
|  | 	--shiki-token-tag: #f07178; | ||||||
|  | 	--shiki-token-attribute: #ffcb6b; | ||||||
|  | 	--shiki-token-property: #82b1ff; | ||||||
|  | 	--shiki-token-operator: #89ddff; | ||||||
|  | 	--shiki-token-regex: #c3e88d; | ||||||
|  | 	--shiki-token-class: #ffcb6b; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* Code block with syntax highlighting waiting for JS */ | ||||||
|  | ${host}[data-js=todo] { | ||||||
|  | 	border: 1px solid var(--border); | ||||||
|  | 	border-radius: var(--border-radius); | ||||||
|  | 	padding: 1rem; | ||||||
|  | 	background-color: var(--code-bg); | ||||||
|  | 	position: relative; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* Add a subtle loading indicator */ | ||||||
|  | ${host}[data-js=todo]::before { | ||||||
|  | 	content: "Loading syntax highlighting..."; | ||||||
|  | 	position: absolute; | ||||||
|  | 	top: 0.5rem; | ||||||
|  | 	right: 0.5rem; | ||||||
|  | 	font-size: 0.75rem; | ||||||
|  | 	color: var(--text-light); | ||||||
|  | 	background-color: var(--bg); | ||||||
|  | 	padding: 0.25rem 0.5rem; | ||||||
|  | 	border-radius: var(--border-radius); | ||||||
|  | 	opacity: 0.7; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* All code blocks should have consistent font and sizing */ | ||||||
|  | ${host} code { | ||||||
|  | 	font-family: var(--font-mono); | ||||||
|  | 	font-size: inherit; | ||||||
|  | 	line-height: 1.5; | ||||||
|  | 	padding: 0; | ||||||
|  | } | ||||||
|  | ${host} pre { | ||||||
|  | 	margin-block: 0; | ||||||
|  | 	font-size: inherit; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* Ensure line numbers (if added) are styled appropriately */ | ||||||
|  | ${host} .line-number { | ||||||
|  | 	user-select: none; | ||||||
|  | 	opacity: 0.5; | ||||||
|  | 	margin-right: 1rem; | ||||||
|  | 	min-width: 1.5rem; | ||||||
|  | 	display: inline-block; | ||||||
|  | 	text-align: right; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* If there's a copy button, style it */ | ||||||
|  | ${host} .copy-button { | ||||||
|  | 	position: absolute; | ||||||
|  | 	top: 0.5rem; | ||||||
|  | 	right: 0.5rem; | ||||||
|  | 	background-color: var(--bg); | ||||||
|  | 	color: var(--text); | ||||||
|  | 	border: 1px solid var(--border); | ||||||
|  | 	border-radius: var(--border-radius); | ||||||
|  | 	padding: 0.25rem 0.5rem; | ||||||
|  | 	font-size: 0.75rem; | ||||||
|  | 	cursor: pointer; | ||||||
|  | 	opacity: 0; | ||||||
|  | 	transition: opacity 0.2s ease; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | ${host}:hover .copy-button { | ||||||
|  | 	opacity: 1; | ||||||
|  | } | ||||||
|  | `; | ||||||
|  | import { el } from "deka-dom-el"; | ||||||
|  | /** | ||||||
|  |  * Prints code to the page and registers flems to make it interactive. | ||||||
|  |  * @param {object} attrs | ||||||
|  |  * @param {string} [attrs.id] | ||||||
|  |  * @param {string} [attrs.className] | ||||||
|  |  * @param {URL} [attrs.src] Example code file path | ||||||
|  |  * @param {string} [attrs.content] Example code | ||||||
|  |  * @param {"js"|"ts"|"html"|"css"|"shell"} [attrs.language="js"] Language of the code | ||||||
|  |  * @param {string} [attrs.page_id] ID of the page, if setted it registers shiki | ||||||
|  |  * */ | ||||||
|  | export function code({ id, src, content, language= "js", className= host.slice(1), page_id }){ | ||||||
|  | 	if(src) content= s.cat(src); | ||||||
|  | 	content= normalizeIndentation(content); | ||||||
|  | 	let dataJS; | ||||||
|  | 	if(page_id){ | ||||||
|  | 		registerClientPart(page_id); | ||||||
|  | 		dataJS= "todo"; | ||||||
|  | 	} | ||||||
|  | 	return el("div", { id, className, dataJS, tabIndex: 0 }).append( | ||||||
|  | 		el("code", { className: "language-"+language, textContent: content.trim() }) | ||||||
|  | 	); | ||||||
|  | } | ||||||
|  | export function pre({ content }){ | ||||||
|  | 	content= normalizeIndentation(content); | ||||||
|  | 	return el("pre").append(el("code", content.trim())); | ||||||
|  | } | ||||||
|  | let is_registered= {}; | ||||||
|  | /** @param {string} page_id */ | ||||||
|  | function registerClientPart(page_id){ | ||||||
|  | 	if(is_registered[page_id]) return; | ||||||
|  |  | ||||||
|  | 	// Add Shiki with a more reliable loading method | ||||||
|  | 	document.head.append( | ||||||
|  | 		// Use a newer version of Shiki with better performance | ||||||
|  | 		el("script", { src: "https://cdn.jsdelivr.net/npm/shiki@0.14.3/dist/index.unpkg.iife.js", defer: true }), | ||||||
|  | 	); | ||||||
|  |  | ||||||
|  | 	registerClientFile( | ||||||
|  | 		new URL("./code.js.js", import.meta.url), | ||||||
|  | 		{ | ||||||
|  | 			head: el("script", { type: "module" }), | ||||||
|  | 		} | ||||||
|  | 	); | ||||||
|  |  | ||||||
|  | 	is_registered[page_id]= true; | ||||||
|  | } | ||||||
|  | /** @param {string} src */ | ||||||
|  | function normalizeIndentation(src){ | ||||||
|  | 	const lines= src.split("\n"); | ||||||
|  | 	const min_indent= Math.min(...lines.map(line=> line.search(/\S/)).filter(i=> i >= 0)); | ||||||
|  | 	return lines.map(line=> line.slice(min_indent)).join("\n"); | ||||||
|  | } | ||||||
							
								
								
									
										61
									
								
								docs/components/code.js.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								docs/components/code.js.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,61 @@ | |||||||
|  | try { | ||||||
|  | 	// Initialize Shiki with our custom theme | ||||||
|  | 	const highlighter = await globalThis.shiki.getHighlighter({ | ||||||
|  | 		theme: "css-variables", | ||||||
|  | 		langs: ["javascript", "typescript", "css", "html", "shell"], | ||||||
|  | 	}); | ||||||
|  |  | ||||||
|  | 	// Find all code blocks that need highlighting | ||||||
|  | 	const codeBlocks = document.querySelectorAll('div[data-js="todo"] code[class*="language-"]'); | ||||||
|  |  | ||||||
|  | 	// Process each code block | ||||||
|  | 	codeBlocks.forEach((block) => { | ||||||
|  | 		try { | ||||||
|  | 			// Get the language from the class | ||||||
|  | 			const langClass = block.className.match(/language-(\w+)/); | ||||||
|  |  | ||||||
|  | 			// Map the language to Shiki format | ||||||
|  | 			let lang = langClass ? langClass[1] : 'javascript'; | ||||||
|  | 			if (lang === 'js') lang = 'javascript'; | ||||||
|  | 			if (lang === 'ts') lang = 'typescript'; | ||||||
|  |  | ||||||
|  | 			// Mark the container as processed | ||||||
|  | 			block.parentElement.dataset.js = "done"; | ||||||
|  |  | ||||||
|  | 			// Highlight the code | ||||||
|  | 			const code = block.textContent; | ||||||
|  | 			const html = highlighter.codeToHtml(code, { lang }); | ||||||
|  |  | ||||||
|  | 			// Insert the highlighted HTML | ||||||
|  | 			block.innerHTML = html; | ||||||
|  |  | ||||||
|  | 			// Add copy button functionality | ||||||
|  | 			const copyBtn = document.createElement('button'); | ||||||
|  | 			copyBtn.className = 'copy-button'; | ||||||
|  | 			copyBtn.textContent = 'Copy'; | ||||||
|  | 			copyBtn.setAttribute('aria-label', 'Copy code to clipboard'); | ||||||
|  | 			copyBtn.addEventListener('click', () => { | ||||||
|  | 				navigator.clipboard.writeText(code).then(() => { | ||||||
|  | 					copyBtn.textContent = 'Copied!'; | ||||||
|  | 					setTimeout(() => { | ||||||
|  | 						copyBtn.textContent = 'Copy'; | ||||||
|  | 					}, 2000); | ||||||
|  | 				}); | ||||||
|  | 			}); | ||||||
|  |  | ||||||
|  | 			// Add the copy button to the code block container | ||||||
|  | 			block.parentElement.appendChild(copyBtn); | ||||||
|  | 		} catch (err) { | ||||||
|  | 			console.error('Error highlighting code block:', err); | ||||||
|  | 			// Make sure we don't leave the block in a pending state | ||||||
|  | 			block.parentElement.dataset.js = "error"; | ||||||
|  | 		} | ||||||
|  | 	}); | ||||||
|  | } catch (err) { | ||||||
|  | 	console.error('Failed to initialize Shiki:', err); | ||||||
|  |  | ||||||
|  | 	// Fallback: at least mark blocks as processed so they don't show loading indicator | ||||||
|  | 	document.querySelectorAll('div[data-js="todo"]').forEach(block => { | ||||||
|  | 		block.dataset.js = "error"; | ||||||
|  | 	}); | ||||||
|  | } | ||||||
							
								
								
									
										176
									
								
								docs/components/converter.html.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										176
									
								
								docs/components/converter.html.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,176 @@ | |||||||
|  | import { styles } from "../ssr.js"; | ||||||
|  |  | ||||||
|  | styles.css` | ||||||
|  | #html-to-dde-converter { | ||||||
|  | 	grid-column: full-main; | ||||||
|  | 	display: flex; | ||||||
|  | 	flex-direction: column; | ||||||
|  | 	gap: 1.5rem; | ||||||
|  | 	padding: 1.5rem; | ||||||
|  | 	border-radius: var(--border-radius); | ||||||
|  | 	background-color: var(--bg-sidebar); | ||||||
|  | 	box-shadow: var(--shadow); | ||||||
|  | 	border: 1px solid var(--border); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #html-to-dde-converter h3 { | ||||||
|  | 	margin-top: 0; | ||||||
|  | 	color: var(--primary); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #html-to-dde-converter .description { | ||||||
|  | 	color: var(--text-light); | ||||||
|  | 	font-size: 0.95rem; | ||||||
|  | 	margin-top: -1rem; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #html-to-dde-converter .converter-form { | ||||||
|  | 	display: flex; | ||||||
|  | 	flex-direction: column; | ||||||
|  | 	gap: 1rem; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #html-to-dde-converter .input-group, | ||||||
|  | #html-to-dde-converter .output-group { | ||||||
|  | 	display: flex; | ||||||
|  | 	flex-direction: column; | ||||||
|  | 	gap: 0.5rem; | ||||||
|  | } | ||||||
|  | #html-to-dde-converter [type="number"]{ | ||||||
|  | 	width: 3em; | ||||||
|  | 	font-variant-numeric: tabular-nums; | ||||||
|  | 	font-size: 1rem; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #html-to-dde-converter label { | ||||||
|  | 	font-weight: 500; | ||||||
|  | 	display: flex; | ||||||
|  | 	justify-content: space-between; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #html-to-dde-converter .options { | ||||||
|  | 	display: flex; | ||||||
|  | 	flex-wrap: wrap; | ||||||
|  | 	gap: 1rem; | ||||||
|  | 	margin-bottom: 0.5rem; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #html-to-dde-converter .option-group { | ||||||
|  | 	display: flex; | ||||||
|  | 	align-items: center; | ||||||
|  | 	gap: 0.5rem; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #html-to-dde-converter textarea { | ||||||
|  | 	font-family: var(--font-mono); | ||||||
|  | 	font-size: 0.9rem; | ||||||
|  | 	padding: 1rem; | ||||||
|  | 	border-radius: var(--border-radius); | ||||||
|  | 	border: 1px solid var(--border); | ||||||
|  | 	background-color: var(--bg); | ||||||
|  | 	color: var(--text); | ||||||
|  | 	min-height: 200px; | ||||||
|  | 	height: 25em; | ||||||
|  | 	resize: vertical; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #html-to-dde-converter textarea:focus { | ||||||
|  | 	outline: 2px solid var(--primary-light); | ||||||
|  | 	outline-offset: 1px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #html-to-dde-converter .button-group { | ||||||
|  | 	display: flex; | ||||||
|  | 	gap: 0.5rem; | ||||||
|  | 	justify-content: space-between; | ||||||
|  | 	align-items: center; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #html-to-dde-converter button { | ||||||
|  | 	padding: 0.5rem 1rem; | ||||||
|  | 	border-radius: var(--border-radius); | ||||||
|  | 	border: none; | ||||||
|  | 	background-color: var(--primary); | ||||||
|  | 	color: var(--button-text); | ||||||
|  | 	font-weight: 500; | ||||||
|  | 	cursor: pointer; | ||||||
|  | 	transition: background-color 0.2s ease; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #html-to-dde-converter button:hover { | ||||||
|  | 	background-color: var(--primary-dark); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #html-to-dde-converter button.secondary { | ||||||
|  | 	background-color: transparent; | ||||||
|  | 	border: 1px solid var(--border); | ||||||
|  | 	color: var(--text); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #html-to-dde-converter button.secondary:hover { | ||||||
|  | 	background-color: var(--bg); | ||||||
|  | 	border-color: var(--primary); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #html-to-dde-converter .copy-button { | ||||||
|  | 	background-color: var(--secondary); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #html-to-dde-converter .copy-button:hover { | ||||||
|  | 	background-color: var(--secondary-dark); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #html-to-dde-converter .status { | ||||||
|  | 	font-size: 0.9rem; | ||||||
|  | 	color: var(--text-light); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #html-to-dde-converter .error { | ||||||
|  | 	color: hsl(0, 100%, 60%); | ||||||
|  | 	font-size: 0.9rem; | ||||||
|  | 	margin-top: 0.5rem; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* Sample HTML examples list */ | ||||||
|  | #html-to-dde-converter .examples-list { | ||||||
|  | 	display: flex; | ||||||
|  | 	flex-wrap: wrap; | ||||||
|  | 	gap: 0.5rem; | ||||||
|  | 	margin-top: 0.5rem; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #html-to-dde-converter .example-button { | ||||||
|  | 	font-size: 0.85rem; | ||||||
|  | 	padding: 0.25rem 0.5rem; | ||||||
|  | } | ||||||
|  | `; | ||||||
|  |  | ||||||
|  | import { ireland } from "./ireland.html.js"; | ||||||
|  | import { el } from "deka-dom-el"; | ||||||
|  | const fileURL= url=> new URL(url, import.meta.url); | ||||||
|  |  | ||||||
|  | export function converter({ page_id }){ | ||||||
|  | 	registerClientPart(page_id); | ||||||
|  | 	return el(ireland, { | ||||||
|  | 		src: fileURL("./converter.js.js"), | ||||||
|  | 		exportName: "converter", | ||||||
|  | 		page_id, | ||||||
|  | 	}); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | let is_registered= {}; | ||||||
|  | /** @param {string} page_id */ | ||||||
|  | function registerClientPart(page_id){ | ||||||
|  | 	if(is_registered[page_id]) return; | ||||||
|  |  | ||||||
|  | 	document.head.append( | ||||||
|  | 		el("script", { | ||||||
|  | 			// src: "https://unpkg.com/@beforesemicolon/html-parser/dist/client.js", | ||||||
|  | 			src: "https://cdn.jsdelivr.net/npm/@beforesemicolon/html-parser/dist/client.js", | ||||||
|  | 			type: "text/javascript", | ||||||
|  | 			charset: "utf-8", | ||||||
|  | 			defer: true | ||||||
|  | 		}), | ||||||
|  | 	); | ||||||
|  | 	is_registered[page_id]= true; | ||||||
|  | } | ||||||
							
								
								
									
										384
									
								
								docs/components/converter.js.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										384
									
								
								docs/components/converter.js.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,384 @@ | |||||||
|  | import { el, on } from "deka-dom-el"; | ||||||
|  | import { S } from "deka-dom-el/signals"; | ||||||
|  | const { parse }= globalThis.BFS || { parse(){ return { children: [ "not implemented" ] } } }; | ||||||
|  | // Example HTML snippets | ||||||
|  | const examples = [ | ||||||
|  | { | ||||||
|  | 	name: "Simple Component", | ||||||
|  | 	html: `<div class="card"> | ||||||
|  | 	<img src="image.jpg" alt="Card Image" class="card-image"> | ||||||
|  | 	<h2 class="card-title">Card Title</h2> | ||||||
|  | 	<p class="card-text">This is a simple card component</p> | ||||||
|  | 	<button aria-pressed="mixed" type="button" class="card-button">Click Me</button> | ||||||
|  | </div>` | ||||||
|  | }, | ||||||
|  | { | ||||||
|  | 	name: "Navigation", | ||||||
|  | 	html: `<nav class="main-nav"> | ||||||
|  | 	<ul> | ||||||
|  | 		<li><a href="/" class="active">Home</a></li> | ||||||
|  | 		<li><a href="/about">About</a></li> | ||||||
|  | 		<li><a href="/services">Services</a></li> | ||||||
|  | 		<li><a href="/contact">Contact</a></li> | ||||||
|  | 	</ul> | ||||||
|  | </nav>` | ||||||
|  | }, | ||||||
|  | { | ||||||
|  | 	name: "Form", | ||||||
|  | 	html: `<form class="contact-form" onsubmit="submitForm(event)"> | ||||||
|  | 	<div class="form-group"> | ||||||
|  | 		<label for="name">Name:</label> | ||||||
|  | 		<input type="text" id="name" name="name" required> | ||||||
|  | 	</div> | ||||||
|  | 	<div class="form-group"> | ||||||
|  | 		<label for="email">Email:</label> | ||||||
|  | 		<input type="email" id="email" name="email" required> | ||||||
|  | 	</div> | ||||||
|  | 	<div class="form-group"> | ||||||
|  | 		<label for="message">Message:</label> | ||||||
|  | 		<textarea id="message" name="message" rows="4" required></textarea> | ||||||
|  | 	</div> | ||||||
|  | 	<button type="submit" class="submit-btn">Send Message</button> | ||||||
|  | </form>` | ||||||
|  | } | ||||||
|  | ]; | ||||||
|  |  | ||||||
|  | // Convert HTML to dd<el> code | ||||||
|  | function convertHTMLtoDDE(html, options = {}) { | ||||||
|  |  | ||||||
|  | 	try { | ||||||
|  | 		const parsed = parse(html); | ||||||
|  | 		const content = parsed.children[0] || parsed.childNodes[0]; | ||||||
|  | 		return !content ? "" : nodeToDDE(content, options); | ||||||
|  | 	} catch (error) { | ||||||
|  | 		console.error("Parsing error:", error); | ||||||
|  | 		return `// Error parsing HTML: ${error.message}`; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Node types based on standard DOM nodeType values | ||||||
|  | const NODE_TYPE = { | ||||||
|  | 	ELEMENT: 1,      // Standard element node (equivalent to node.type === "element") | ||||||
|  | 	TEXT: 3,         // Text node (equivalent to node.type === "text") | ||||||
|  | 	COMMENT: 8       // Comment node (equivalent to node.type === "comment") | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | // Convert a parsed node to dd<el> code | ||||||
|  | function nodeToDDE(node, options = {}, level = 0) { | ||||||
|  | 	const tab= options.indent === "-1" ? "\t" : " ".repeat(options.indent); | ||||||
|  | 	const indent = tab.repeat(level); | ||||||
|  | 	const nextIndent = tab.repeat(level + 1); | ||||||
|  |  | ||||||
|  | 	const { nodeType } = node; | ||||||
|  | 	// Handle text nodes | ||||||
|  | 	if (nodeType === NODE_TYPE.TEXT) { | ||||||
|  | 		const text = el("i", { innerText: node.nodeValue }).textContent; | ||||||
|  | 		if (!text.trim()) return null; | ||||||
|  |  | ||||||
|  | 		// Return as plain text or template string for longer text | ||||||
|  | 		return text.includes("\n") || text.includes('"') | ||||||
|  | 			? `\`${text}\`` | ||||||
|  | 			: `"${text}"`; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// Handle comment nodes | ||||||
|  | 	if (nodeType === NODE_TYPE.COMMENT) { | ||||||
|  | 		const text = node.nodeValue; | ||||||
|  | 		if (!text.trim()) return null; | ||||||
|  | 		return text.includes("\n") | ||||||
|  | 			? [ "/*", ...text.trim().split("\n").map(l=> tab+l), "*/" ] | ||||||
|  | 			: [ `// ${text}` ]; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// For element nodes | ||||||
|  | 	if (nodeType === NODE_TYPE.ELEMENT) { | ||||||
|  | 		// Special case for SVG elements | ||||||
|  | 		const isNS = node.tagName === "svg"; | ||||||
|  | 		const elFunction = isNS ? "elNS" : "el"; | ||||||
|  |  | ||||||
|  | 		// Get tag name | ||||||
|  | 		let tagStr = `"${node.tagName}"`; | ||||||
|  |  | ||||||
|  | 		// Process attributes | ||||||
|  | 		const attrs = []; | ||||||
|  | 		const sets = { | ||||||
|  | 			aria: {}, | ||||||
|  | 			data: {}, | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		for (const { name: key, value } of node.attributes) { | ||||||
|  | 			// Handle class attribute | ||||||
|  | 			if (key === "class") { | ||||||
|  | 				attrs.push(`className: "${value}"`); | ||||||
|  | 				continue; | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			// Handle style attribute | ||||||
|  | 			if (key === "style") { | ||||||
|  | 				if (options.styleAsObject) { | ||||||
|  | 				// Convert inline style to object | ||||||
|  | 				const styleObj = {}; | ||||||
|  | 				value.split(";").forEach(part => { | ||||||
|  | 					const [propRaw, valueRaw] = part.split(":"); | ||||||
|  | 					if (propRaw && valueRaw) { | ||||||
|  | 						const prop = propRaw.trim(); | ||||||
|  | 						const propCamel = prop.replace(/-([a-z])/g, (_, c) => c.toUpperCase()); | ||||||
|  | 						styleObj[propCamel] = valueRaw.trim(); | ||||||
|  | 					} | ||||||
|  | 				}); | ||||||
|  |  | ||||||
|  | 				if (Object.keys(styleObj).length > 0) { | ||||||
|  | 					const styleStr = JSON.stringify(styleObj).replace(/"([^"]+)":/g, "$1:"); | ||||||
|  | 					attrs.push(`style: ${styleStr}`); | ||||||
|  | 				} | ||||||
|  | 				} else { | ||||||
|  | 					// Keep as string | ||||||
|  | 					attrs.push(`style: "${value}"`); | ||||||
|  | 				} | ||||||
|  | 				continue; | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			// Handle boolean attributes | ||||||
|  | 			if (value === "" || value === key) { | ||||||
|  | 				attrs.push(`${key}: true`); | ||||||
|  | 				continue; | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			// Handle data/aria attributes | ||||||
|  | 			if (key.startsWith("data-") || key.startsWith("aria-")) { | ||||||
|  | 				const keyName = key.startsWith("aria-") ? "aria" : "data"; | ||||||
|  | 				const keyCamel = key.slice(keyName.length + 1).replace(/-([a-z])/g, (_, c) => c.toUpperCase()); | ||||||
|  | 				sets[keyName][keyCamel] = value; | ||||||
|  | 				continue; | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			// Regular attributes | ||||||
|  | 			const keyRegular = key==="for" | ||||||
|  | 				? "htmlFor" | ||||||
|  | 				: key.startsWith("on") | ||||||
|  | 				? `"=${key}"` | ||||||
|  | 				: key.replace(/-([a-z])/g, (_, c) => c.toUpperCase()); | ||||||
|  | 			attrs.push(`${keyRegular}: "${value}"`); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		// Process sets | ||||||
|  | 		for (const [name, set] of Object.entries(sets)) { | ||||||
|  | 		if(options.dataAttrsAsCamel) | ||||||
|  | 			for (const [key, value] of Object.entries(set)) | ||||||
|  | 			attrs.push(`${name}${key[0].toUpperCase() + key.substring(1)}: "${value}"`); | ||||||
|  | 		else { | ||||||
|  | 			const setStr= Object.entries(set).map(([key, value]) => `${key}: "${value}"`).join(","); | ||||||
|  | 			if (setStr !== "") | ||||||
|  | 			attrs.push(`${name}set: { ${setStr} }`); | ||||||
|  | 		} | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		// Process children | ||||||
|  | 		const children = []; | ||||||
|  | 		for (const child of node.childNodes) { | ||||||
|  | 			const childCode = nodeToDDE(child, options, level + 1); | ||||||
|  | 			if (!childCode) continue; | ||||||
|  |  | ||||||
|  | 			children.push(childCode); | ||||||
|  | 		} | ||||||
|  | 		if(node.childNodes.length===1 && node.childNodes[0].nodeType===NODE_TYPE.TEXT){ | ||||||
|  | 			const textContent= children.pop().slice(1, -1); | ||||||
|  | 			attrs.unshift(`textContent: "${textContent}"`); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		// Build the element creation code | ||||||
|  | 		let result = `${elFunction}("${node.tagName.toLowerCase()}"`; | ||||||
|  |  | ||||||
|  | 		// Add attributes if any | ||||||
|  | 		if (attrs.length > 0) { | ||||||
|  | 		const tooLong= attrs.join(``).length+result.length > 55; | ||||||
|  | 		if(options.expaned || tooLong || attrs.length > 3) | ||||||
|  | 			result += `, {\n${nextIndent}${attrs.join(`,\n${nextIndent}`)},\n${indent}}`; | ||||||
|  | 		else | ||||||
|  | 			result += `, { ${attrs.join(", ")} }`; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		// Add children if any | ||||||
|  | 		if (children.length > 0) { | ||||||
|  | 			const chs= children.map(ch=> | ||||||
|  | 				Array.isArray(ch) ? ch.map(l=> nextIndent + l).join("\n") : | ||||||
|  | 				nextIndent + ch + ","); | ||||||
|  | 			result += `).append(\n${chs.join("\n")}\n${indent})`; | ||||||
|  | 		} else { | ||||||
|  | 			result += ")"; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		return result; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return null; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | export function converter() { | ||||||
|  | 	// State for the converter | ||||||
|  | 	const htmlInput = S(examples[0].html); | ||||||
|  | 	const error = S(""); | ||||||
|  |  | ||||||
|  | 	const status = S(""); | ||||||
|  | 	const showStatus= msg => { | ||||||
|  | 		status.set(msg); | ||||||
|  | 		// Clear status after 3 seconds | ||||||
|  | 		setTimeout(() => status.set(""), 3000); | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	// Options state | ||||||
|  | 	const options = { | ||||||
|  | 		styleAsObject: { | ||||||
|  | 			title: "Convert style to object", | ||||||
|  | 			value: S(true), | ||||||
|  | 		}, | ||||||
|  | 		dataAttrsAsCamel: { | ||||||
|  | 			title: "dataKey/ariaKey (or dataset/ariaset)", | ||||||
|  | 			value: S(true), | ||||||
|  | 		}, | ||||||
|  | 		indent: { | ||||||
|  | 			title: "Indentation (-1 for tabs)", | ||||||
|  | 			value: S("-1"), | ||||||
|  | 			type: "number", | ||||||
|  | 		}, | ||||||
|  | 		expaned: { | ||||||
|  | 			title: "Force multiline", | ||||||
|  | 			value: S(false), | ||||||
|  | 		} | ||||||
|  | 	}; | ||||||
|  | 	const getOptions = ()=> Object.fromEntries(Object.entries(options) | ||||||
|  | 		.map(([key, option]) => ([ | ||||||
|  | 			key, | ||||||
|  | 			option.value.get() | ||||||
|  | 		])) | ||||||
|  | 	); | ||||||
|  |  | ||||||
|  | 	// Update the dd<el> output when input or options change | ||||||
|  | 	const ddeOutput = S(() => { | ||||||
|  | 		try { | ||||||
|  | 			const result = convertHTMLtoDDE(htmlInput.get(), getOptions()); | ||||||
|  | 			error.set(""); | ||||||
|  | 			return result; | ||||||
|  | 		} catch (err) { | ||||||
|  | 			error.set(`Error: ${err.message}`); | ||||||
|  | 			return ""; | ||||||
|  | 		} | ||||||
|  | 	}); | ||||||
|  |  | ||||||
|  | 	// Event handlers | ||||||
|  | 	const onConvert = on("submit", e => { | ||||||
|  | 		e.preventDefault(); | ||||||
|  | 		htmlInput.set(htmlInput.get(), true); | ||||||
|  | 		showStatus("Converted!"); | ||||||
|  | 	}); | ||||||
|  |  | ||||||
|  | 	const onCopy = on("click", async () => { | ||||||
|  | 		if (!ddeOutput.get()) return; | ||||||
|  |  | ||||||
|  | 		try { | ||||||
|  | 			await navigator.clipboard.writeText(ddeOutput.get()); | ||||||
|  | 			showStatus("Copied to clipboard!"); | ||||||
|  | 		} catch (err) { | ||||||
|  | 			error.set(`Could not copy: ${err.message}`); | ||||||
|  | 		} | ||||||
|  | 	}); | ||||||
|  | 	const onClear = on("click", () => { | ||||||
|  | 		htmlInput.set(""); | ||||||
|  | 		showStatus("Input cleared"); | ||||||
|  | 	}); | ||||||
|  | 	const onExampleLoad = (example) => on("click", () => { | ||||||
|  | 		htmlInput.set(example.html); | ||||||
|  | 		showStatus(`Loaded "${example.name}" example`); | ||||||
|  | 	}); | ||||||
|  |  | ||||||
|  | 	const optionsElements = () => Object.entries(options) | ||||||
|  | 		.map(([key, option]) => | ||||||
|  | 			el("label", { className: "option-group" }).append( | ||||||
|  | 				option.type==="number" | ||||||
|  | 					? el("input", { | ||||||
|  | 						type: option.type || "checkbox", | ||||||
|  | 						name: key, | ||||||
|  | 						value: option.value.get(), | ||||||
|  | 						max: 10, | ||||||
|  | 					}, on("change", e => option.value.set(e.target.value))) | ||||||
|  | 					: el("input", { | ||||||
|  | 						type: option.type || "checkbox", | ||||||
|  | 						name: key, | ||||||
|  | 						checked: option.value.get(), | ||||||
|  | 					}, on("change", e => option.value.set(e.target.checked))), | ||||||
|  | 				option.title, | ||||||
|  | 			) | ||||||
|  | 	); | ||||||
|  | 	const exampleButtons = examples.map(example => | ||||||
|  | 		el("button", { | ||||||
|  | 			type: "button", | ||||||
|  | 			className: "secondary example-button" | ||||||
|  | 		}, onExampleLoad(example)).append(example.name) | ||||||
|  | 	); | ||||||
|  |  | ||||||
|  | 	return el("div", { id: "html-to-dde-converter" }).append( | ||||||
|  | 		el("h3", "HTML to dd<el> Converter"), | ||||||
|  | 		el("p", { className: "description" }).append( | ||||||
|  | 			"Convert HTML markup to dd<el> JavaScript code. Paste your HTML below or choose from an example." | ||||||
|  | 		), | ||||||
|  |  | ||||||
|  | 		el("form", { className: "converter-form" }, onConvert).append( | ||||||
|  | 			el("div", { className: "options" }).append(...optionsElements()), | ||||||
|  |  | ||||||
|  | 			el("div", { className: "examples-list" }).append( | ||||||
|  | 				el("label", "Examples: "), | ||||||
|  | 				...exampleButtons | ||||||
|  | 			), | ||||||
|  |  | ||||||
|  | 			el("div", { className: "editor-container" }).append( | ||||||
|  | 				el("div", { className: "input-group" }).append( | ||||||
|  | 					el("label", { htmlFor: "html-input" }).append( | ||||||
|  | 						"HTML Input", | ||||||
|  | 						el("div", { className: "button-group" }).append( | ||||||
|  | 							el("button", { | ||||||
|  | 								type: "button", | ||||||
|  | 								className: "secondary", | ||||||
|  | 								title: "Clear input" | ||||||
|  | 							}, onClear).append("Clear") | ||||||
|  | 						) | ||||||
|  | 					), | ||||||
|  | 					el("textarea", { | ||||||
|  | 						id: "html-input", | ||||||
|  | 						spellcheck: false, | ||||||
|  | 						value: htmlInput, | ||||||
|  | 						placeholder: "Paste your HTML here or choose an example", | ||||||
|  | 						oninput: e => htmlInput.set(e.target.value) | ||||||
|  | 					}) | ||||||
|  | 				), | ||||||
|  |  | ||||||
|  | 				el("div", { className: "output-group" }).append( | ||||||
|  | 					el("label", { htmlFor: "dde-output" }).append( | ||||||
|  | 						"dd<el> Output", | ||||||
|  | 						el("div", { className: "button-group" }).append( | ||||||
|  | 							el("button", { | ||||||
|  | 								textContent: "Copy", | ||||||
|  | 								type: "button", | ||||||
|  | 								className: "copy-button", | ||||||
|  | 								title: "Copy to clipboard", | ||||||
|  | 								disabled: S(() => !ddeOutput.get()) | ||||||
|  | 							}, onCopy) | ||||||
|  | 						) | ||||||
|  | 					), | ||||||
|  | 					el("textarea", { | ||||||
|  | 						id: "dde-output", | ||||||
|  | 						readonly: true, | ||||||
|  | 						spellcheck: false, | ||||||
|  | 						placeholder: "The converted dd<el> code will appear here", | ||||||
|  | 						value: S(() => ddeOutput.get() || "// Convert HTML to see results here") | ||||||
|  | 					}) | ||||||
|  | 				) | ||||||
|  | 			), | ||||||
|  |  | ||||||
|  | 			el("div", { className: "button-group" }).append( | ||||||
|  | 				S.el(error, error => !error ? el() : el("div", { className: "error" }).append(error)), | ||||||
|  | 				el("div", { className: "status", textContent: status }), | ||||||
|  | 				el("button", { type: "submit" }).append("Convert") | ||||||
|  | 			) | ||||||
|  | 		) | ||||||
|  | 	); | ||||||
|  | } | ||||||
							
								
								
									
										163
									
								
								docs/components/example.html.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										163
									
								
								docs/components/example.html.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,163 @@ | |||||||
|  | import { styles } from "../ssr.js"; | ||||||
|  | const host= "."+example.name; | ||||||
|  | styles.css` | ||||||
|  | ${host} { | ||||||
|  | 	grid-column: full-main; | ||||||
|  | 	height: calc(4/6 * var(--body-max-width)); | ||||||
|  | 	border-radius: var(--border-radius); | ||||||
|  | 	box-shadow: var(--shadow); | ||||||
|  | 	border: 1px solid var(--border); | ||||||
|  | } | ||||||
|  | ${host} .runtime { | ||||||
|  | 	background-color: whitesmoke; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* CodeMirror styling to match our theme */ | ||||||
|  | .CodeMirror { | ||||||
|  | 	height: 100% !important; | ||||||
|  | 	font-family: var(--font-mono) !important; | ||||||
|  | 	font-size: .85rem !important; | ||||||
|  | 	line-height: 1.5 !important; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* Dark mode styles for CodeMirror */ | ||||||
|  | .CodeMirror, .CodeMirror-gutters { | ||||||
|  | 	background: var(--code-bg) !important; | ||||||
|  | 	color: var(--text) !important; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* Light mode adjustments for CodeMirror - using CSS variables */ | ||||||
|  | @media (prefers-color-scheme: light) { | ||||||
|  | 	/* Core syntax elements */ | ||||||
|  | 	.cm-s-material .cm-keyword { color: var(--shiki-token-keyword, #d73a49) !important; } | ||||||
|  | 	.cm-s-material .cm-atom { color: var(--shiki-token-constant, #005cc5) !important; } | ||||||
|  | 	.cm-s-material .cm-number { color: var(--shiki-token-number, #005cc5) !important; } | ||||||
|  | 	.cm-s-material .cm-def { color: var(--shiki-token-function, #6f42c1) !important; } | ||||||
|  | 	.cm-s-material .cm-variable { color: var(--shiki-token-variable, #24292e) !important; } | ||||||
|  | 	.cm-s-material .cm-variable-2 { color: var(--shiki-token-variable, #24292e) !important; } | ||||||
|  | 	.cm-s-material .cm-variable-3 { color: var(--shiki-token-variable, #24292e) !important; } | ||||||
|  | 	.cm-s-material .cm-property { color: var(--shiki-token-property, #005cc5) !important; } | ||||||
|  | 	.cm-s-material .cm-operator { color: var(--shiki-token-operator, #d73a49) !important; } | ||||||
|  | 	.cm-s-material .cm-comment { color: var(--shiki-token-comment, #6a737d) !important; } | ||||||
|  | 	.cm-s-material .cm-string { color: var(--shiki-token-string, #22863a) !important; } | ||||||
|  | 	.cm-s-material .cm-string-2 { color: var(--shiki-token-string, #22863a) !important; } | ||||||
|  | 	.cm-s-material .cm-tag { color: var(--shiki-token-tag, #22863a) !important; } | ||||||
|  | 	.cm-s-material .cm-attribute { color: var(--shiki-token-attribute, #005cc5) !important; } | ||||||
|  | 	.cm-s-material .cm-bracket { color: var(--shiki-token-punctuation, #24292e) !important; } | ||||||
|  | 	.cm-s-material .cm-punctuation { color: var(--shiki-token-punctuation, #24292e) !important; } | ||||||
|  | 	.cm-s-material .cm-link { color: var(--shiki-token-link, #0366d6) !important; } | ||||||
|  | 	.cm-s-material .cm-error { color: #f44336 !important; } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* Handle theme toggle */ | ||||||
|  | html[data-theme="light"] .CodeMirror { | ||||||
|  | 	background: #f5f7fa !important; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | html[data-theme="light"] .CodeMirror-gutters { | ||||||
|  | 	background: #f5f7fa !important; | ||||||
|  | 	border-right: 1px solid #e5e7eb !important; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* Also apply the same styles to CodeMirror with data-theme */ | ||||||
|  | html[data-theme="light"] .cm-s-material .cm-keyword { color: var(--shiki-token-keyword, #d73a49) !important; } | ||||||
|  | html[data-theme="light"] .cm-s-material .cm-atom { color: var(--shiki-token-constant, #005cc5) !important; } | ||||||
|  | html[data-theme="light"] .cm-s-material .cm-number { color: var(--shiki-token-number, #005cc5) !important; } | ||||||
|  | html[data-theme="light"] .cm-s-material .cm-def { color: var(--shiki-token-function, #6f42c1) !important; } | ||||||
|  | html[data-theme="light"] .cm-s-material .cm-variable { color: var(--shiki-token-variable, #24292e) !important; } | ||||||
|  | html[data-theme="light"] .cm-s-material .cm-variable-2 { color: var(--shiki-token-variable, #24292e) !important; } | ||||||
|  | html[data-theme="light"] .cm-s-material .cm-variable-3 { color: var(--shiki-token-variable, #24292e) !important; } | ||||||
|  | html[data-theme="light"] .cm-s-material .cm-property { color: var(--shiki-token-property, #005cc5) !important; } | ||||||
|  | html[data-theme="light"] .cm-s-material .cm-operator { color: var(--shiki-token-operator, #d73a49) !important; } | ||||||
|  | html[data-theme="light"] .cm-s-material .cm-comment { color: var(--shiki-token-comment, #6a737d) !important; } | ||||||
|  | html[data-theme="light"] .cm-s-material .cm-string { color: var(--shiki-token-string, #22863a) !important; } | ||||||
|  | html[data-theme="light"] .cm-s-material .cm-string-2 { color: var(--shiki-token-string, #22863a) !important; } | ||||||
|  | html[data-theme="light"] .cm-s-material .cm-tag { color: var(--shiki-token-tag, #22863a) !important; } | ||||||
|  | html[data-theme="light"] .cm-s-material .cm-attribute { color: var(--shiki-token-attribute, #005cc5) !important; } | ||||||
|  | html[data-theme="light"] .cm-s-material .cm-bracket { color: var(--shiki-token-punctuation, #24292e) !important; } | ||||||
|  | html[data-theme="light"] .cm-s-material .cm-punctuation { color: var(--shiki-token-punctuation, #24292e) !important; } | ||||||
|  | html[data-theme="light"] .cm-s-material .cm-link { color: var(--shiki-token-link, #0366d6) !important; } | ||||||
|  | html[data-theme="light"] .cm-s-material .cm-error { color: #f44336 !important; } | ||||||
|  |  | ||||||
|  | /* Mobile adjustments */ | ||||||
|  | @media (max-width: 767px) { | ||||||
|  | 	${host} { | ||||||
|  | 		height: 50vh; | ||||||
|  | 	} | ||||||
|  | 	${host} main { | ||||||
|  | 		flex-grow: 1; | ||||||
|  | 		display: flex; | ||||||
|  | 		flex-direction: column; | ||||||
|  | 	} | ||||||
|  | 	${host} main > * { | ||||||
|  | 		width: 100%; | ||||||
|  | 		max-width: 100% !important; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | ${host}[data-variant=big]{ | ||||||
|  | 	height: 150vh; | ||||||
|  |  | ||||||
|  | 	main { | ||||||
|  | 		flex-flow: column nowrap; | ||||||
|  | 		flex-grow: 1; | ||||||
|  | 	} | ||||||
|  | 	main > * { | ||||||
|  | 		width: 100%; | ||||||
|  | 		max-width: 100% !important; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | `; | ||||||
|  |  | ||||||
|  | const dde_content= s.cat(new URL("../../dist/esm-with-signals.js", import.meta.url)).toString(); | ||||||
|  |  | ||||||
|  | import { el } from "deka-dom-el"; | ||||||
|  | import { code } from "./code.html.js"; | ||||||
|  | import { relative } from "node:path"; | ||||||
|  | /** | ||||||
|  |  * Prints code to the page and registers flems to make it interactive. | ||||||
|  |  * @param {object} attrs | ||||||
|  |  * @param {URL} attrs.src Example code file path | ||||||
|  |  * @param {"js"|"ts"|"html"|"css"} [attrs.language="js"] Language of the code | ||||||
|  |  * @param {"normal"|"big"} [attrs.variant="normal"] Size of the example | ||||||
|  |  * @param {string} attrs.page_id ID of the page | ||||||
|  |  * */ | ||||||
|  | export function example({ src, language= "js", variant= "normal", page_id }){ | ||||||
|  | 	registerClientPart(page_id); | ||||||
|  | 	const content= s.cat(src).toString() | ||||||
|  | 		.replaceAll(/ from "deka-dom-el(\/signals)?";/g, ' from "./esm-with-signals.js";'); | ||||||
|  | 	const id= "code-example-"+generateCodeId(src); | ||||||
|  | 	return el().append( | ||||||
|  | 		el(code, { id, content, language, className: example.name }, el=> el.dataset.variant= variant), | ||||||
|  | 		elCode({ id, content, extension: "."+language }) | ||||||
|  | 	); | ||||||
|  | } | ||||||
|  | function elCode({ id, content, extension: name }){ | ||||||
|  | 	const options= JSON.stringify({ | ||||||
|  | 		files: [{ name, content }, { name: "esm-with-signals.js", content: dde_content }], | ||||||
|  | 		toolbar: false | ||||||
|  | 	}); | ||||||
|  | 	return el("script", `Flems(document.getElementById("${id}"), JSON.parse(${JSON.stringify(options)}));`); | ||||||
|  | } | ||||||
|  | let is_registered= {}; | ||||||
|  | /** @param {string} page_id */ | ||||||
|  | function registerClientPart(page_id){ | ||||||
|  | 	if(is_registered[page_id]) return; | ||||||
|  |  | ||||||
|  | 	document.head.append( | ||||||
|  | 		el("script", { src: "https://flems.io/flems.html", type: "text/javascript", charset: "utf-8" }), | ||||||
|  | 	); | ||||||
|  | 	is_registered[page_id]= true; | ||||||
|  | } | ||||||
|  | const store_prev= new Map(); | ||||||
|  | /** @param {URL} src */ | ||||||
|  | function generateCodeId(src){ | ||||||
|  | 	const candidate= parseInt(relative((new URL("..", import.meta.url)).pathname, src.pathname) | ||||||
|  | 		.split("") | ||||||
|  | 		.map(ch=> ch.charCodeAt(0)) | ||||||
|  | 		.join(""), 10) | ||||||
|  | 		.toString(36) | ||||||
|  | 		.replace(/000+/g, ""); | ||||||
|  | 	const count= 1 + ( store_prev.get(candidate) || 0 ); | ||||||
|  | 	store_prev.set(candidate, count); | ||||||
|  | 	return count.toString()+"-"+candidate; | ||||||
|  | } | ||||||
							
								
								
									
										374
									
								
								docs/components/examples/case-studies/data-dashboard.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										374
									
								
								docs/components/examples/case-studies/data-dashboard.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,374 @@ | |||||||
|  | /** | ||||||
|  |  * Case Study: Data Dashboard with Charts | ||||||
|  |  * | ||||||
|  |  * This example demonstrates: | ||||||
|  |  * - Integration with a third-party charting library | ||||||
|  |  * - Data fetching and state management | ||||||
|  |  * - Responsive layout design | ||||||
|  |  * - Multiple interactive components working together | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | import { el, on } from "deka-dom-el"; | ||||||
|  | import { S } from "deka-dom-el/signals"; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Data Dashboard Component with Chart Integration | ||||||
|  |  * @returns {HTMLElement} Dashboard element | ||||||
|  |  */ | ||||||
|  | export function DataDashboard() { | ||||||
|  | 	// Mock data for demonstration | ||||||
|  | 	const DATA = { | ||||||
|  | 		sales: [42, 58, 65, 49, 72, 85, 63, 70, 78, 89, 95, 86], | ||||||
|  | 		visitors: [1420, 1620, 1750, 1850, 2100, 2400, 2250, 2500, 2750, 2900, 3100, 3200], | ||||||
|  | 		conversion: [2.9, 3.5, 3.7, 2.6, 3.4, 3.5, 2.8, 2.8, 2.8, 3.1, 3.0, 2.7], | ||||||
|  | 		months: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'] | ||||||
|  | 	}; | ||||||
|  | 	const years = [2022, 2023, 2024]; | ||||||
|  | 	const dataTypes = [ | ||||||
|  | 		{ id: 'sales', label: 'Sales', unit: 'K' }, | ||||||
|  | 		{ id: 'visitors', label: 'Visitors', unit: '' }, | ||||||
|  | 		{ id: 'conversion', label: 'Conversion Rate', unit: '%' } | ||||||
|  | 	]; | ||||||
|  |  | ||||||
|  | 	// Filter options | ||||||
|  | 	const selectedYear = S(2024); | ||||||
|  | 	const onYearChange = on("change", e => { | ||||||
|  | 		selectedYear.set(parseInt(/** @type {HTMLSelectElement} */(e.target).value)); | ||||||
|  | 		loadData(); | ||||||
|  | 	}); | ||||||
|  | 	const selectedDataType = S(/** @type {'sales' | 'visitors' | 'conversion'} */ ('sales')); | ||||||
|  | 	const onDataTypeChange = on("click", e => { | ||||||
|  | 		const type = /** @type {'sales' | 'visitors' | 'conversion'} */( | ||||||
|  | 			/** @type {HTMLButtonElement} */(e.currentTarget).dataset.type); | ||||||
|  | 		selectedDataType.set(type); | ||||||
|  | 	}); | ||||||
|  | 	const currentDataType = S(() => dataTypes.find(type => type.id === selectedDataType.get())); | ||||||
|  | 	const selectedData = S(() => DATA[selectedDataType.get()]); | ||||||
|  |  | ||||||
|  | 	// Values based on filters | ||||||
|  | 	const totalValue = S(() => selectedData.get().reduce((sum, value) => sum + value, 0)); | ||||||
|  | 	const averageValue = S(() => { | ||||||
|  | 		const data = selectedData.get(); | ||||||
|  | 		return data.reduce((sum, value) => sum + value, 0) / data.length; | ||||||
|  | 	}); | ||||||
|  | 	const highestValue = S(() => Math.max(...selectedData.get())); | ||||||
|  |  | ||||||
|  | 	// Simulate data loading | ||||||
|  | 	const isLoading = S(false); | ||||||
|  | 	const error = S(null); | ||||||
|  | 	function loadData() { | ||||||
|  | 		isLoading.set(true); | ||||||
|  | 		error.set(null); | ||||||
|  |  | ||||||
|  | 		// Simulate API call | ||||||
|  | 		setTimeout(() => { | ||||||
|  | 			if (Math.random() > 0.9) { | ||||||
|  | 				// Simulate occasional error | ||||||
|  | 				error.set('Failed to load data. Please try again.'); | ||||||
|  | 			} | ||||||
|  | 			isLoading.set(false); | ||||||
|  | 		}, 800); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// Reactive chart rendering | ||||||
|  | 	const chart = S(()=> { | ||||||
|  | 		const chart= el("canvas", { id: "chart-canvas", width: 800, height: 400 }); | ||||||
|  | 		const ctx = chart.getContext('2d'); | ||||||
|  | 		const data = selectedData.get(); | ||||||
|  | 		const months = DATA.months; | ||||||
|  | 		const width = chart.width; | ||||||
|  | 		const height = chart.height; | ||||||
|  | 		const maxValue = Math.max(...data) * 1.1; | ||||||
|  | 		const barWidth = width / data.length - 10; | ||||||
|  |  | ||||||
|  | 		// Clear canvas | ||||||
|  | 		ctx.clearRect(0, 0, width, height); | ||||||
|  |  | ||||||
|  | 		// Draw background grid | ||||||
|  | 		ctx.beginPath(); | ||||||
|  | 		ctx.strokeStyle = '#f0f0f0'; | ||||||
|  | 		ctx.lineWidth = 1; | ||||||
|  | 		for(let i = 0; i < 5; i++) { | ||||||
|  | 			const y = height - (height * (i / 5)) - 30; | ||||||
|  | 			ctx.moveTo(50, y); | ||||||
|  | 			ctx.lineTo(width - 20, y); | ||||||
|  |  | ||||||
|  | 			// Draw grid labels | ||||||
|  | 			ctx.fillStyle = '#999'; | ||||||
|  | 			ctx.font = '12px Arial'; | ||||||
|  | 			ctx.fillText(Math.round(maxValue * (i / 5)).toString(), 20, y + 5); | ||||||
|  | 		} | ||||||
|  | 		ctx.stroke(); | ||||||
|  |  | ||||||
|  | 		// Draw bars | ||||||
|  | 		data.forEach((value, index) => { | ||||||
|  | 			const x = index * (barWidth + 10) + 60; | ||||||
|  | 			const barHeight = (value / maxValue) * (height - 60); | ||||||
|  |  | ||||||
|  | 			// Bar | ||||||
|  | 			ctx.fillStyle = '#4a90e2'; | ||||||
|  | 			ctx.fillRect(x, height - barHeight - 30, barWidth, barHeight); | ||||||
|  |  | ||||||
|  | 			// Month label | ||||||
|  | 			ctx.fillStyle = '#666'; | ||||||
|  | 			ctx.font = '12px Arial'; | ||||||
|  | 			ctx.fillText(months[index], x + barWidth/2 - 10, height - 10); | ||||||
|  | 		}); | ||||||
|  |  | ||||||
|  | 		// Chart title | ||||||
|  | 		ctx.fillStyle = '#333'; | ||||||
|  | 		ctx.font = 'bold 14px Arial'; | ||||||
|  | 		ctx.fillText(`${currentDataType.get().label} (${selectedYear.get()})`, width/2 - 80, 20); | ||||||
|  | 		return chart; | ||||||
|  | 	}); | ||||||
|  |  | ||||||
|  | 	return el("div", { className: "dashboard" }).append( | ||||||
|  | 		el("header", { className: "dashboard-header" }).append( | ||||||
|  | 			el("h1", "Sales Performance Dashboard"), | ||||||
|  | 			el("div", { className: "year-filter" }).append( | ||||||
|  | 				el("label", { htmlFor: "yearSelect", textContent: "Select Year:" }), | ||||||
|  | 				el("select", { id: "yearSelect" }, | ||||||
|  | 					on.defer(el=> el.value = selectedYear.get().toString()), | ||||||
|  | 					onYearChange | ||||||
|  | 				).append( | ||||||
|  | 					...years.map(year => el("option", { value: year, textContent: year })) | ||||||
|  | 				) | ||||||
|  | 			) | ||||||
|  | 		), | ||||||
|  |  | ||||||
|  | 		S.el(error, errorMsg => !errorMsg | ||||||
|  | 			? el() | ||||||
|  | 			: el("div", { className: "error-message" }).append( | ||||||
|  | 					el("p", errorMsg), | ||||||
|  | 					el("button", { textContent: "Retry", type: "button" }, on("click", loadData)), | ||||||
|  | 				), | ||||||
|  | 		), | ||||||
|  |  | ||||||
|  | 		S.el(isLoading, loading => !loading | ||||||
|  | 			? el() | ||||||
|  | 			: el("div", { className: "loading-spinner" }) | ||||||
|  | 		), | ||||||
|  |  | ||||||
|  | 		// Main dashboard content | ||||||
|  | 		el("div", { className: "dashboard-content" }).append( | ||||||
|  | 			// Metrics cards | ||||||
|  | 			el("div", { className: "metrics-container" }).append( | ||||||
|  | 				el("div", { className: "metric-card" }).append( | ||||||
|  | 					el("h3", "Total"), | ||||||
|  | 					el("#text", S(() => `${totalValue.get().toLocaleString()}${currentDataType.get().unit}`)), | ||||||
|  | 				), | ||||||
|  | 				el("div", { className: "metric-card" }).append( | ||||||
|  | 					el("h3", "Average"), | ||||||
|  | 					el("#text", S(() => `${averageValue.get().toFixed(1)}${currentDataType.get().unit}`)), | ||||||
|  | 				), | ||||||
|  | 				el("div", { className: "metric-card" }).append( | ||||||
|  | 					el("h3", "Highest"), | ||||||
|  | 					el("#text", S(() => `${highestValue.get()}${currentDataType.get().unit}`)), | ||||||
|  | 				), | ||||||
|  | 			), | ||||||
|  |  | ||||||
|  | 			// Data type selection tabs | ||||||
|  | 			el("div", { className: "data-type-tabs" }).append( | ||||||
|  | 				...dataTypes.map(type => | ||||||
|  | 					el("button", { | ||||||
|  | 						type: "button", | ||||||
|  | 						className: S(() => selectedDataType.get() === type.id ? 'active' : ''), | ||||||
|  | 						dataType: type.id, | ||||||
|  | 						textContent: type.label | ||||||
|  | 					}, onDataTypeChange) | ||||||
|  | 				) | ||||||
|  | 			), | ||||||
|  |  | ||||||
|  | 			// Chart container | ||||||
|  | 			el("div", { className: "chart-container" }).append( | ||||||
|  | 				S.el(chart, chart => chart) | ||||||
|  | 			) | ||||||
|  | 		), | ||||||
|  | 	); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Render the component | ||||||
|  | document.body.append( | ||||||
|  | 	el("div", { style: "padding: 20px; background: #f5f5f5; min-height: 100vh;" }).append( | ||||||
|  | 		el(DataDashboard) | ||||||
|  | 	), | ||||||
|  | 	el("style", ` | ||||||
|  | 			.dashboard { | ||||||
|  | 				font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; | ||||||
|  | 				max-width: 1000px; | ||||||
|  | 				margin: 0 auto; | ||||||
|  | 				padding: 1rem; | ||||||
|  | 				background: #fff; | ||||||
|  | 				box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); | ||||||
|  | 				border-radius: 8px; | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			.dashboard-header { | ||||||
|  | 				display: flex; | ||||||
|  | 				justify-content: space-between; | ||||||
|  | 				align-items: center; | ||||||
|  | 				margin-bottom: 1.5rem; | ||||||
|  | 				padding-bottom: 1rem; | ||||||
|  | 				border-bottom: 1px solid #eee; | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			.dashboard-header h1 { | ||||||
|  | 				font-size: 1.5rem; | ||||||
|  | 				margin: 0; | ||||||
|  | 				color: #333; | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			.year-filter { | ||||||
|  | 				display: flex; | ||||||
|  | 				align-items: center; | ||||||
|  | 				gap: 0.5rem; | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			.year-filter select { | ||||||
|  | 				padding: 0.5rem; | ||||||
|  | 				border: 1px solid #ddd; | ||||||
|  | 				border-radius: 4px; | ||||||
|  | 				font-size: 1rem; | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			.metrics-container { | ||||||
|  | 				display: grid; | ||||||
|  | 				grid-template-columns: repeat(3, 1fr); | ||||||
|  | 				gap: 1rem; | ||||||
|  | 				margin-bottom: 1.5rem; | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			.metric-card { | ||||||
|  | 				background: #f9f9f9; | ||||||
|  | 				border-radius: 8px; | ||||||
|  | 				padding: 1rem; | ||||||
|  | 				text-align: center; | ||||||
|  | 				transition: transform 0.2s ease; | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			.metric-card:hover { | ||||||
|  | 				transform: translateY(-5px); | ||||||
|  | 				box-shadow: 0 5px 15px rgba(0, 0, 0, 0.05); | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			.metric-card h3 { | ||||||
|  | 				margin-top: 0; | ||||||
|  | 				color: #666; | ||||||
|  | 				font-size: 0.9rem; | ||||||
|  | 				margin-bottom: 0.5rem; | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			.metric-card p { | ||||||
|  | 				font-size: 1.5rem; | ||||||
|  | 				font-weight: bold; | ||||||
|  | 				color: #333; | ||||||
|  | 				margin: 0; | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			.data-type-tabs { | ||||||
|  | 				display: flex; | ||||||
|  | 				border-bottom: 1px solid #eee; | ||||||
|  | 				margin-bottom: 1.5rem; | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			.data-type-tabs button { | ||||||
|  | 				background: none; | ||||||
|  | 				border: none; | ||||||
|  | 				padding: 0.75rem 1.5rem; | ||||||
|  | 				font-size: 1rem; | ||||||
|  | 				cursor: pointer; | ||||||
|  | 				color: #666; | ||||||
|  | 				position: relative; | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			.data-type-tabs button.active { | ||||||
|  | 				color: #4a90e2; | ||||||
|  | 				font-weight: 500; | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			.data-type-tabs button.active::after { | ||||||
|  | 				content: ''; | ||||||
|  | 				position: absolute; | ||||||
|  | 				bottom: -1px; | ||||||
|  | 				left: 0; | ||||||
|  | 				width: 100%; | ||||||
|  | 				height: 3px; | ||||||
|  | 				background: #4a90e2; | ||||||
|  | 				border-radius: 3px 3px 0 0; | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			.chart-container { | ||||||
|  | 				background: #fff; | ||||||
|  | 				border-radius: 8px; | ||||||
|  | 				padding: 1rem; | ||||||
|  | 				margin-bottom: 1.5rem; | ||||||
|  | 				box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05); | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			.loading-spinner { | ||||||
|  | 				display: flex; | ||||||
|  | 				justify-content: center; | ||||||
|  | 				align-items: center; | ||||||
|  | 				height: 100px; | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			.loading-spinner::before { | ||||||
|  | 				content: ''; | ||||||
|  | 				width: 40px; | ||||||
|  | 				height: 40px; | ||||||
|  | 				border: 4px solid #f3f3f3; | ||||||
|  | 				border-top: 4px solid #4a90e2; | ||||||
|  | 				border-radius: 50%; | ||||||
|  | 				animation: spin 1s linear infinite; | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			@keyframes spin { | ||||||
|  | 				0% { transform: rotate(0deg); } | ||||||
|  | 				100% { transform: rotate(360deg); } | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			.error-message { | ||||||
|  | 				background: #ffecec; | ||||||
|  | 				color: #e74c3c; | ||||||
|  | 				padding: 1rem; | ||||||
|  | 				border-radius: 4px; | ||||||
|  | 				margin-bottom: 1.5rem; | ||||||
|  | 				display: flex; | ||||||
|  | 				justify-content: space-between; | ||||||
|  | 				align-items: center; | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			.error-message p { | ||||||
|  | 				margin: 0; | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			.error-message button { | ||||||
|  | 				background: #e74c3c; | ||||||
|  | 				color: white; | ||||||
|  | 				border: none; | ||||||
|  | 				border-radius: 4px; | ||||||
|  | 				padding: 0.5rem 1rem; | ||||||
|  | 				cursor: pointer; | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			@media (max-width: 768px) { | ||||||
|  | 				.metrics-container { | ||||||
|  | 					grid-template-columns: 1fr; | ||||||
|  | 				} | ||||||
|  |  | ||||||
|  | 				.dashboard-header { | ||||||
|  | 					flex-direction: column; | ||||||
|  | 					align-items: flex-start; | ||||||
|  | 					gap: 1rem; | ||||||
|  | 				} | ||||||
|  |  | ||||||
|  | 				.year-filter { | ||||||
|  | 					width: 100%; | ||||||
|  | 				} | ||||||
|  |  | ||||||
|  | 				.year-filter select { | ||||||
|  | 					flex-grow: 1; | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		`) | ||||||
|  | ); | ||||||
							
								
								
									
										412
									
								
								docs/components/examples/case-studies/image-gallery.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										412
									
								
								docs/components/examples/case-studies/image-gallery.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,412 @@ | |||||||
|  | /** | ||||||
|  |  * Case Study: Interactive Image Gallery | ||||||
|  |  * | ||||||
|  |  * This example demonstrates: | ||||||
|  |  * - Dynamic loading of content | ||||||
|  |  * - Lightbox functionality | ||||||
|  |  * - Animation handling | ||||||
|  |  * - Keyboard and gesture navigation | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | import { el, memo, on } from "deka-dom-el"; | ||||||
|  | import { S } from "deka-dom-el/signals"; | ||||||
|  |  | ||||||
|  | // Sample image data | ||||||
|  | const imagesSample = (url=> [ | ||||||
|  | 	{ id: 1, src: url+'nature', alt: 'Nature', title: 'Beautiful Landscape' }, | ||||||
|  | 	{ id: 2, src: url+'places', alt: 'City', title: 'Urban Architecture' }, | ||||||
|  | 	{ id: 3, src: url+'people', alt: 'People', title: 'Street Photography' }, | ||||||
|  | 	{ id: 4, src: url+'food', alt: 'Food', title: 'Culinary Delights' }, | ||||||
|  | 	{ id: 5, src: url+'animals', alt: 'Animals', title: 'Wildlife' }, | ||||||
|  | 	{ id: 6, src: url+'travel', alt: 'Travel', title: 'Adventure Awaits' }, | ||||||
|  | 	{ id: 7, src: url+'computer', alt: 'Technology', title: 'Modern Tech' }, | ||||||
|  | 	{ id: 8, src: url+'music', alt: 'Art', title: 'Creative Expression' }, | ||||||
|  | ])('https://api.algobook.info/v1/randomimage?category='); | ||||||
|  | /** | ||||||
|  |  * Interactive Image Gallery Component | ||||||
|  |  * @returns {HTMLElement} Gallery element | ||||||
|  |  */ | ||||||
|  | export function ImageGallery(images= imagesSample) { | ||||||
|  | 	const filterTag = S('all'); | ||||||
|  | 	const imagesToDisplay = S(() => { | ||||||
|  | 		const tag = filterTag.get(); | ||||||
|  | 		if (tag === 'all') return images; | ||||||
|  | 		else return images.filter(img => img.alt.toLowerCase() === tag); | ||||||
|  | 	}) | ||||||
|  | 	const onFilterChange = tag => on("click", () => { | ||||||
|  | 		filterTag.set(tag); | ||||||
|  | 	}); | ||||||
|  |  | ||||||
|  | 	// Lightbox | ||||||
|  | 	const selectedImageId = S(null); | ||||||
|  | 	const selectedImage = S(() => { | ||||||
|  | 		const id = selectedImageId.get(); | ||||||
|  | 		return id ? images.find(img => img.id === id) : null; | ||||||
|  | 	}); | ||||||
|  | 	const isLightboxOpen = S(() => selectedImage.get() !== null); | ||||||
|  | 	const onImageClick = id => on("click", () => { | ||||||
|  | 		selectedImageId.set(id); | ||||||
|  | 		document.body.style.overflow = 'hidden'; // Prevent scrolling when lightbox is open | ||||||
|  |  | ||||||
|  | 		// Add keyboard event listeners when lightbox opens | ||||||
|  | 		document.addEventListener('keydown', handleKeyDown); | ||||||
|  | 	}); | ||||||
|  | 	const closeLightbox = () => { | ||||||
|  | 		selectedImageId.set(null); | ||||||
|  | 		document.body.style.overflow = ''; // Restore scrolling | ||||||
|  |  | ||||||
|  | 		// Remove keyboard event listeners when lightbox closes | ||||||
|  | 		document.removeEventListener('keydown', handleKeyDown); | ||||||
|  | 	}; | ||||||
|  | 	const onPrevImage = e => { | ||||||
|  | 		e.stopPropagation(); // Prevent closing the lightbox | ||||||
|  | 		const images = imagesToDisplay.get(); | ||||||
|  | 		const currentId = selectedImageId.get(); | ||||||
|  | 		const currentIndex = images.findIndex(img => img.id === currentId); | ||||||
|  | 		const prevIndex = (currentIndex - 1 + images.length) % images.length; | ||||||
|  | 		selectedImageId.set(images[prevIndex].id); | ||||||
|  | 	}; | ||||||
|  | 	const onNextImage = e => { | ||||||
|  | 		e.stopPropagation(); // Prevent closing the lightbox | ||||||
|  | 		const images = imagesToDisplay.get(); | ||||||
|  | 		const currentId = selectedImageId.get(); | ||||||
|  | 		const currentIndex = images.findIndex(img => img.id === currentId); | ||||||
|  | 		const nextIndex = (currentIndex + 1) % images.length; | ||||||
|  | 		selectedImageId.set(images[nextIndex].id); | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	// Keyboard navigation handler | ||||||
|  | 	function handleKeyDown(e) { | ||||||
|  | 		switch(e.key) { | ||||||
|  | 			case 'Escape': | ||||||
|  | 				closeLightbox(); | ||||||
|  | 				break; | ||||||
|  | 			case 'ArrowLeft': | ||||||
|  | 				document.querySelector('.lightbox-prev-btn').click(); | ||||||
|  | 				break; | ||||||
|  | 			case 'ArrowRight': | ||||||
|  | 				document.querySelector('.lightbox-next-btn').click(); | ||||||
|  | 				break; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// Build the gallery UI | ||||||
|  | 	return el("div", { className: "gallery-container" }).append( | ||||||
|  | 		// Gallery header | ||||||
|  | 		el("header", { className: "gallery-header" }).append( | ||||||
|  | 			el("h1", "Interactive Image Gallery"), | ||||||
|  | 			el("p", "Click on any image to view it in the lightbox. Use arrow keys for navigation.") | ||||||
|  | 		), | ||||||
|  |  | ||||||
|  | 		// Filter options | ||||||
|  | 		el("div", { className: "gallery-filters" }).append( | ||||||
|  | 			el("button", { | ||||||
|  | 				classList: { active: S(() => filterTag.get() === 'all') }, | ||||||
|  | 				textContent: "All" | ||||||
|  | 			}, onFilterChange('all')), | ||||||
|  | 			el("button", { | ||||||
|  | 				classList: { active: S(() => filterTag.get() === 'nature') }, | ||||||
|  | 				textContent: "Nature" | ||||||
|  | 			}, onFilterChange('nature')), | ||||||
|  | 			el("button", { | ||||||
|  | 				classList: { active: S(() => filterTag.get() === 'urban') }, | ||||||
|  | 				textContent: "Urban" | ||||||
|  | 			}, onFilterChange('urban')), | ||||||
|  | 			el("button", { | ||||||
|  | 				classList: { active: S(() => filterTag.get() === 'people') }, | ||||||
|  | 				textContent: "People" | ||||||
|  | 			}, onFilterChange('people')) | ||||||
|  | 		), | ||||||
|  |  | ||||||
|  | 		// Image grid | ||||||
|  | 		el("div", { className: "gallery-grid" }).append( | ||||||
|  | 			S.el(imagesToDisplay, images => | ||||||
|  | 				images.map(image => | ||||||
|  | 					memo(image.id, ()=> | ||||||
|  | 						el("div", { | ||||||
|  | 							className: "gallery-item", | ||||||
|  | 							dataTag: image.alt.toLowerCase() | ||||||
|  | 						}).append( | ||||||
|  | 							el("img", { | ||||||
|  | 								src: image.src, | ||||||
|  | 								alt: image.alt, | ||||||
|  | 								loading: "lazy" | ||||||
|  | 							}, onImageClick(image.id)), | ||||||
|  | 							el("div", { className: "gallery-item-caption" }).append( | ||||||
|  | 								el("h3", image.title), | ||||||
|  | 								el("p", image.alt) | ||||||
|  | 							) | ||||||
|  | 						) | ||||||
|  | 					) | ||||||
|  | 				) | ||||||
|  | 			) | ||||||
|  | 		), | ||||||
|  |  | ||||||
|  | 		// Lightbox (only shown when an image is selected) | ||||||
|  | 		S.el(isLightboxOpen, open => !open | ||||||
|  | 			? el() | ||||||
|  | 			: el("div", { className: "lightbox-overlay" }, on("click", closeLightbox)).append( | ||||||
|  | 					el("div", { | ||||||
|  | 						className: "lightbox-content", | ||||||
|  | 						onClick: e => e.stopPropagation() // Prevent closing when clicking inside | ||||||
|  | 					}).append( | ||||||
|  | 						el("button", { | ||||||
|  | 							className: "lightbox-close-btn", | ||||||
|  | 							"aria-label": "Close lightbox" | ||||||
|  | 						}, on("click", closeLightbox)).append("×"), | ||||||
|  |  | ||||||
|  | 						el("button", { | ||||||
|  | 							className: "lightbox-prev-btn", | ||||||
|  | 							"aria-label": "Previous image" | ||||||
|  | 						}, on("click", onPrevImage)).append("❮"), | ||||||
|  |  | ||||||
|  | 						el("button", { | ||||||
|  | 							className: "lightbox-next-btn", | ||||||
|  | 							"aria-label": "Next image" | ||||||
|  | 						}, on("click", onNextImage)).append("❯"), | ||||||
|  |  | ||||||
|  | 						S.el(selectedImage, img => !img | ||||||
|  | 							? el() | ||||||
|  | 							: el("div", { className: "lightbox-image-container" }).append( | ||||||
|  | 								el("img", { | ||||||
|  | 									src: img.src, | ||||||
|  | 									alt: img.alt, | ||||||
|  | 									className: "lightbox-image" | ||||||
|  | 								}), | ||||||
|  | 								el("div", { className: "lightbox-caption" }).append( | ||||||
|  | 									el("h2", img.title), | ||||||
|  | 									el("p", img.alt) | ||||||
|  | 								) | ||||||
|  | 							) | ||||||
|  | 						) | ||||||
|  | 					) | ||||||
|  | 				) | ||||||
|  | 		), | ||||||
|  | 	); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Render the component | ||||||
|  | document.body.append( | ||||||
|  | 	el("div", { style: "padding: 20px; background: #f5f5f5; min-height: 100vh;" }).append( | ||||||
|  | 		el(ImageGallery) | ||||||
|  | 	), | ||||||
|  | 	el("style", ` | ||||||
|  | 		.gallery-container { | ||||||
|  | 			font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; | ||||||
|  | 			max-width: 1200px; | ||||||
|  | 			margin: 0 auto; | ||||||
|  | 			padding: 2rem; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		.gallery-header { | ||||||
|  | 			text-align: center; | ||||||
|  | 			margin-bottom: 2rem; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		.gallery-header h1 { | ||||||
|  | 			margin-bottom: 0.5rem; | ||||||
|  | 			color: #333; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		.gallery-header p { | ||||||
|  | 			color: #666; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		.gallery-filters { | ||||||
|  | 			display: flex; | ||||||
|  | 			justify-content: center; | ||||||
|  | 			margin-bottom: 2rem; | ||||||
|  | 			flex-wrap: wrap; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		.gallery-filters button { | ||||||
|  | 			background: none; | ||||||
|  | 			border: none; | ||||||
|  | 			padding: 0.5rem 1.5rem; | ||||||
|  | 			margin: 0 0.5rem; | ||||||
|  | 			font-size: 1rem; | ||||||
|  | 			cursor: pointer; | ||||||
|  | 			border-radius: 30px; | ||||||
|  | 			transition: all 0.3s ease; | ||||||
|  | 			color: #555; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		.gallery-filters button:hover { | ||||||
|  | 			background: #f0f0f0; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		.gallery-filters button.active { | ||||||
|  | 			background: #4a90e2; | ||||||
|  | 			color: white; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		.gallery-grid { | ||||||
|  | 			display: grid; | ||||||
|  | 			grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); | ||||||
|  | 			gap: 1.5rem; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		.gallery-item { | ||||||
|  | 			position: relative; | ||||||
|  | 			border-radius: 8px; | ||||||
|  | 			overflow: hidden; | ||||||
|  | 			box-shadow: 0 3px 10px rgba(0, 0, 0, 0.1); | ||||||
|  | 			transition: transform 0.3s ease, box-shadow 0.3s ease; | ||||||
|  | 			cursor: pointer; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		.gallery-item:hover { | ||||||
|  | 			transform: translateY(-5px); | ||||||
|  | 			box-shadow: 0 10px 20px rgba(0, 0, 0, 0.15); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		.gallery-item img { | ||||||
|  | 			width: 100%; | ||||||
|  | 			height: 200px; | ||||||
|  | 			object-fit: cover; | ||||||
|  | 			display: block; | ||||||
|  | 			transition: transform 0.5s ease; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		.gallery-item:hover img { | ||||||
|  | 			transform: scale(1.05); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		.gallery-item-caption { | ||||||
|  | 			position: absolute; | ||||||
|  | 			bottom: 0; | ||||||
|  | 			left: 0; | ||||||
|  | 			right: 0; | ||||||
|  | 			background: linear-gradient(to top, rgba(0, 0, 0, 0.7), transparent); | ||||||
|  | 			color: white; | ||||||
|  | 			padding: 1rem; | ||||||
|  | 			transform: translateY(100%); | ||||||
|  | 			transition: transform 0.3s ease; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		.gallery-item:hover .gallery-item-caption { | ||||||
|  | 			transform: translateY(0); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		.gallery-item-caption h3 { | ||||||
|  | 			margin: 0 0 0.5rem; | ||||||
|  | 			font-size: 1.2rem; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		.gallery-item-caption p { | ||||||
|  | 			margin: 0; | ||||||
|  | 			font-size: 0.9rem; | ||||||
|  | 			opacity: 0.8; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		/* Lightbox styles */ | ||||||
|  | 		.lightbox-overlay { | ||||||
|  | 			position: fixed; | ||||||
|  | 			top: 0; | ||||||
|  | 			left: 0; | ||||||
|  | 			right: 0; | ||||||
|  | 			bottom: 0; | ||||||
|  | 			background: rgba(0, 0, 0, 0.9); | ||||||
|  | 			display: flex; | ||||||
|  | 			justify-content: center; | ||||||
|  | 			align-items: center; | ||||||
|  | 			z-index: 1000; | ||||||
|  | 			padding: 2rem; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		.lightbox-content { | ||||||
|  | 			position: relative; | ||||||
|  | 			max-width: 90%; | ||||||
|  | 			max-height: 90%; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		.lightbox-image-container { | ||||||
|  | 			overflow: hidden; | ||||||
|  | 			border-radius: 4px; | ||||||
|  | 			box-shadow: 0 0 30px rgba(0, 0, 0, 0.5); | ||||||
|  | 			background: #000; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		.lightbox-image { | ||||||
|  | 			max-width: 100%; | ||||||
|  | 			max-height: 80vh; | ||||||
|  | 			display: block; | ||||||
|  | 			margin: 0 auto; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		.lightbox-caption { | ||||||
|  | 			background: #222; | ||||||
|  | 			color: white; | ||||||
|  | 			padding: 1rem; | ||||||
|  | 			text-align: center; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		.lightbox-caption h2 { | ||||||
|  | 			margin: 0 0 0.5rem; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		.lightbox-caption p { | ||||||
|  | 			margin: 0; | ||||||
|  | 			opacity: 0.8; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		.lightbox-close-btn, | ||||||
|  | 		.lightbox-prev-btn, | ||||||
|  | 		.lightbox-next-btn { | ||||||
|  | 			background: rgba(0, 0, 0, 0.5); | ||||||
|  | 			color: white; | ||||||
|  | 			border: none; | ||||||
|  | 			font-size: 1.5rem; | ||||||
|  | 			width: 50px; | ||||||
|  | 			height: 50px; | ||||||
|  | 			border-radius: 50%; | ||||||
|  | 			display: flex; | ||||||
|  | 			justify-content: center; | ||||||
|  | 			align-items: center; | ||||||
|  | 			cursor: pointer; | ||||||
|  | 			transition: background 0.3s ease; | ||||||
|  | 			position: absolute; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		.lightbox-close-btn:hover, | ||||||
|  | 		.lightbox-prev-btn:hover, | ||||||
|  | 		.lightbox-next-btn:hover { | ||||||
|  | 			background: rgba(0, 0, 0, 0.8); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		.lightbox-close-btn { | ||||||
|  | 			top: -25px; | ||||||
|  | 			right: -25px; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		.lightbox-prev-btn { | ||||||
|  | 			left: -25px; | ||||||
|  | 			top: 50%; | ||||||
|  | 			transform: translateY(-50%); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		.lightbox-next-btn { | ||||||
|  | 			right: -25px; | ||||||
|  | 			top: 50%; | ||||||
|  | 			transform: translateY(-50%); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		@media (max-width: 768px) { | ||||||
|  | 			.gallery-container { | ||||||
|  | 				padding: 1rem; | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			.gallery-grid { | ||||||
|  | 				grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); | ||||||
|  | 				gap: 1rem; | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			.lightbox-prev-btn, | ||||||
|  | 			.lightbox-next-btn { | ||||||
|  | 				width: 40px; | ||||||
|  | 				height: 40px; | ||||||
|  | 				font-size: 1.2rem; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	`) | ||||||
|  | ); | ||||||
							
								
								
									
										339
									
								
								docs/components/examples/case-studies/interactive-form.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										339
									
								
								docs/components/examples/case-studies/interactive-form.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,339 @@ | |||||||
|  | /** | ||||||
|  |  * Case Study: Interactive Form with Validation | ||||||
|  |  * | ||||||
|  |  * This example demonstrates: | ||||||
|  |  * - Form handling with real-time validation | ||||||
|  |  * - Reactive UI updates based on input state | ||||||
|  |  * - Complex form state management | ||||||
|  |  * - Clean separation of concerns (data, validation, UI) | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | import { dispatchEvent, el, on, scope } from "deka-dom-el"; | ||||||
|  | import { S } from "deka-dom-el/signals"; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * @typedef {Object} FormState | ||||||
|  |  * @property {string} name | ||||||
|  |  * @property {string} email | ||||||
|  |  * @property {string} password | ||||||
|  |  * @property {string} confirmPassword | ||||||
|  |  * @property {boolean} agreedToTerms | ||||||
|  |  * */ | ||||||
|  | /** | ||||||
|  |  * Interactive Form with Validation Component | ||||||
|  |  * @returns {HTMLElement} Form element | ||||||
|  |  */ | ||||||
|  | export function InteractiveForm() { | ||||||
|  | 	const submitted = S(false); | ||||||
|  | 	/** @type {FormState|null} */ | ||||||
|  | 	let formState = null; | ||||||
|  | 	/** @param {CustomEvent<FormState>} event */ | ||||||
|  | 	const onSubmit = ({ detail }) => { | ||||||
|  | 		submitted.set(true); | ||||||
|  | 		formState = detail; | ||||||
|  | 	}; | ||||||
|  | 	const onAnotherAccount = () => { | ||||||
|  | 		submitted.set(false) | ||||||
|  | 		formState = null; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	return el("div", { className: "form-container" }).append( | ||||||
|  | 		S.el(submitted, s => s | ||||||
|  | 			? el("div", { className: "success-message" }).append( | ||||||
|  | 				el("h3", "Thank you for registering!"), | ||||||
|  | 				el("p", `Welcome, ${formState.name}! Your account has been created successfully.`), | ||||||
|  | 				el("button", { textContent: "Register another account", type: "button" }, | ||||||
|  | 					on("click", onAnotherAccount) | ||||||
|  | 				), | ||||||
|  | 			) | ||||||
|  | 			: el(Form, { initial: formState }, on("form:submit", onSubmit)) | ||||||
|  | 		) | ||||||
|  | 	); | ||||||
|  | } | ||||||
|  | /** | ||||||
|  |  * Form Component | ||||||
|  |  * @type {(props: { initial: FormState | null }) => HTMLElement} | ||||||
|  |  * */ | ||||||
|  | export function Form({ initial }) { | ||||||
|  | 	const { host }= scope; | ||||||
|  | 	// Form state management | ||||||
|  | 	const formState = S(initial || { | ||||||
|  | 		name: '', | ||||||
|  | 		email: '', | ||||||
|  | 		password: '', | ||||||
|  | 		confirmPassword: '', | ||||||
|  | 		agreedToTerms: false | ||||||
|  | 	}, { | ||||||
|  | 		/** | ||||||
|  | 		 * @template {keyof FormState} K | ||||||
|  | 		 * @param {K} key | ||||||
|  | 		 * @param {FormState[K]} value | ||||||
|  | 		 * */ | ||||||
|  | 		update(key, value) { | ||||||
|  | 			this.value[key] = value; | ||||||
|  | 		} | ||||||
|  | 	}); | ||||||
|  | 	/** | ||||||
|  | 	 * Event handler for input events | ||||||
|  | 	 * @param {"value"|"checked"} prop | ||||||
|  | 	 * @returns {(ev: Event) => void} | ||||||
|  | 	 * */ | ||||||
|  | 	const onChange= prop => ev => { | ||||||
|  | 		const input = /** @type {HTMLInputElement} */(ev.target); | ||||||
|  | 		S.action(formState, "update", /** @type {keyof FormState} */(input.id), input[prop]); | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	// Form validate state | ||||||
|  | 	const nameValid = S(() => formState.get().name.length >= 3); | ||||||
|  | 	const emailValid = S(() => { | ||||||
|  | 		const email = formState.get().email; | ||||||
|  | 		return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email); | ||||||
|  | 	}); | ||||||
|  | 	const passwordValid = S(() => { | ||||||
|  | 		const password = formState.get().password; | ||||||
|  | 		return password.length >= 8 && /[A-Z]/.test(password) && /[0-9]/.test(password); | ||||||
|  | 	}); | ||||||
|  | 	const passwordsMatch = S(() => { | ||||||
|  | 		const { password, confirmPassword } = formState.get(); | ||||||
|  | 		return password === confirmPassword && confirmPassword !== ''; | ||||||
|  | 	}); | ||||||
|  | 	const termsAgreed = S(() => formState.get().agreedToTerms); | ||||||
|  | 	const formValid = S(() => | ||||||
|  | 		nameValid.get() && | ||||||
|  | 		emailValid.get() && | ||||||
|  | 		passwordValid.get() && | ||||||
|  | 		passwordsMatch.get() && | ||||||
|  | 		termsAgreed.get() | ||||||
|  | 	); | ||||||
|  |  | ||||||
|  | 	const dispatcSubmit = dispatchEvent("form:submit", host); | ||||||
|  | 	const onSubmit = on("submit", e => { | ||||||
|  | 		e.preventDefault(); | ||||||
|  | 		if (!formValid.get()) { | ||||||
|  | 			return; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		dispatcSubmit(formState.get()); | ||||||
|  | 	}); | ||||||
|  |  | ||||||
|  | 	// Component UI | ||||||
|  | 	return el("form", { className: "registration-form" }, onSubmit).append( | ||||||
|  | 		el("h2", "Create an Account"), | ||||||
|  |  | ||||||
|  | 		// Name field | ||||||
|  | 		el("div", { classList: { | ||||||
|  | 			"form-group": true, | ||||||
|  | 			valid: nameValid, | ||||||
|  | 			invalid: S(()=> !nameValid.get() && formState.get().name) | ||||||
|  | 		}}).append( | ||||||
|  | 			el("label", { htmlFor: "name", textContent: "Full Name" }), | ||||||
|  | 			el("input", { | ||||||
|  | 				id: "name", | ||||||
|  | 				type: "text", | ||||||
|  | 				value: formState.get().name, | ||||||
|  | 				placeholder: "Enter your full name" | ||||||
|  | 			}, on("input", onChange("value"))), | ||||||
|  | 			el("div", { className: "validation-message", textContent: "Name must be at least 3 characters long" }), | ||||||
|  | 		), | ||||||
|  |  | ||||||
|  | 		// Email field | ||||||
|  | 		el("div", { classList: { | ||||||
|  | 			"form-group": true, | ||||||
|  | 			valid: emailValid, | ||||||
|  | 			invalid: S(()=> !emailValid.get() && formState.get().email) | ||||||
|  | 		}}).append( | ||||||
|  | 			el("label", { htmlFor: "email", textContent: "Email Address" }), | ||||||
|  | 			el("input", { | ||||||
|  | 				id: "email", | ||||||
|  | 				type: "email", | ||||||
|  | 				value: formState.get().email, | ||||||
|  | 				placeholder: "Enter your email address" | ||||||
|  | 			}, on("input", onChange("value"))), | ||||||
|  | 			el("div", { className: "validation-message", textContent: "Please enter a valid email address" }) | ||||||
|  | 		), | ||||||
|  |  | ||||||
|  | 		// Password field | ||||||
|  | 		el("div", { classList: { | ||||||
|  | 			"form-group": true, | ||||||
|  | 			valid: passwordValid, | ||||||
|  | 			invalid: S(()=> !passwordValid.get() && formState.get().password) | ||||||
|  | 		}}).append( | ||||||
|  | 			el("label", { htmlFor: "password", textContent: "Password" }), | ||||||
|  | 			el("input", { | ||||||
|  | 				id: "password", | ||||||
|  | 				type: "password", | ||||||
|  | 				value: formState.get().password, | ||||||
|  | 				placeholder: "Create a password" | ||||||
|  | 			}, on("input", onChange("value"))), | ||||||
|  | 			el("div", { | ||||||
|  | 				className: "validation-message", | ||||||
|  | 				textContent: "Password must be at least 8 characters with at least one uppercase letter and one number", | ||||||
|  | 			}), | ||||||
|  | 		), | ||||||
|  |  | ||||||
|  | 		// Confirm password field | ||||||
|  | 		el("div", { classList: { | ||||||
|  | 			"form-group": true, | ||||||
|  | 			valid: passwordsMatch, | ||||||
|  | 			invalid: S(()=> !passwordsMatch.get() && formState.get().confirmPassword) | ||||||
|  | 		}}).append( | ||||||
|  | 			el("label", { htmlFor: "confirmPassword", textContent: "Confirm Password" }), | ||||||
|  | 			el("input", { | ||||||
|  | 				id: "confirmPassword", | ||||||
|  | 				type: "password", | ||||||
|  | 				value: formState.get().confirmPassword, | ||||||
|  | 				placeholder: "Confirm your password" | ||||||
|  | 			}, on("input", onChange("value"))), | ||||||
|  | 			el("div", { className: "validation-message", textContent: "Passwords must match" }), | ||||||
|  | 		), | ||||||
|  |  | ||||||
|  | 		// Terms agreement | ||||||
|  | 		el("div", { className: "form-group checkbox-group" }).append( | ||||||
|  | 			el("input", { | ||||||
|  | 				id: "agreedToTerms", | ||||||
|  | 				type: "checkbox", | ||||||
|  | 				checked: formState.get().agreedToTerms | ||||||
|  | 			}, on("change", onChange("checked"))), | ||||||
|  | 			el("label", { htmlFor: "agreedToTerms", textContent: "I agree to the Terms and Conditions" }), | ||||||
|  | 		), | ||||||
|  |  | ||||||
|  | 		// Submit button | ||||||
|  | 		el("button", { | ||||||
|  | 			textContent: "Create Account", | ||||||
|  | 			type: "submit", | ||||||
|  | 			className: "submit-button", | ||||||
|  | 			disabled: S(() => !formValid.get()) | ||||||
|  | 		}), | ||||||
|  | 	); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Render the component | ||||||
|  | document.body.append( | ||||||
|  | 	el("div", { style: "padding: 20px; background: #f5f5f5; min-height: 100vh;" }).append( | ||||||
|  | 		el(InteractiveForm) | ||||||
|  | 	), | ||||||
|  | 	el("style", ` | ||||||
|  | 		.form-container { | ||||||
|  | 			font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; | ||||||
|  | 			max-width: 500px; | ||||||
|  | 			margin: 0 auto; | ||||||
|  | 			padding: 2rem; | ||||||
|  | 			border-radius: 8px; | ||||||
|  | 			box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); | ||||||
|  | 			background: #fff; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		h2 { | ||||||
|  | 			margin-top: 0; | ||||||
|  | 			color: #333; | ||||||
|  | 			margin-bottom: 1.5rem; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		.form-group { | ||||||
|  | 			margin-bottom: 1.5rem; | ||||||
|  | 			position: relative; | ||||||
|  | 			transition: all 0.3s ease; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		label { | ||||||
|  | 			display: block; | ||||||
|  | 			margin-bottom: 0.5rem; | ||||||
|  | 			color: #555; | ||||||
|  | 			font-weight: 500; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		input[type="text"], | ||||||
|  | 		input[type="email"], | ||||||
|  | 		input[type="password"] { | ||||||
|  | 			width: 100%; | ||||||
|  | 			padding: 0.75rem; | ||||||
|  | 			border: 1px solid #ddd; | ||||||
|  | 			border-radius: 4px; | ||||||
|  | 			font-size: 1rem; | ||||||
|  | 			transition: border-color 0.3s ease; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		input:focus { | ||||||
|  | 			outline: none; | ||||||
|  | 			border-color: #4a90e2; | ||||||
|  | 			box-shadow: 0 0 0 2px rgba(74, 144, 226, 0.2); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		.checkbox-group { | ||||||
|  | 			display: flex; | ||||||
|  | 			align-items: center; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		.checkbox-group label { | ||||||
|  | 			margin: 0 0 0 0.5rem; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		.validation-message { | ||||||
|  | 			font-size: 0.85rem; | ||||||
|  | 			color: #e74c3c; | ||||||
|  | 			margin-top: 0.5rem; | ||||||
|  | 			height: 0; | ||||||
|  | 			overflow: hidden; | ||||||
|  | 			opacity: 0; | ||||||
|  | 			transition: all 0.3s ease; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		.form-group.invalid .validation-message { | ||||||
|  | 			height: auto; | ||||||
|  | 			opacity: 1; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		.form-group.valid input { | ||||||
|  | 			border-color: #2ecc71; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		.form-group.invalid input { | ||||||
|  | 			border-color: #e74c3c; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		.submit-button { | ||||||
|  | 			background-color: #4a90e2; | ||||||
|  | 			color: white; | ||||||
|  | 			border: none; | ||||||
|  | 			border-radius: 4px; | ||||||
|  | 			padding: 0.75rem 1.5rem; | ||||||
|  | 			font-size: 1rem; | ||||||
|  | 			cursor: pointer; | ||||||
|  | 			transition: background-color 0.3s ease; | ||||||
|  | 			width: 100%; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		.submit-button:hover:not(:disabled) { | ||||||
|  | 			background-color: #3a7bc8; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		.submit-button:disabled { | ||||||
|  | 			background-color: #b5b5b5; | ||||||
|  | 			cursor: not-allowed; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		.success-message { | ||||||
|  | 			text-align: center; | ||||||
|  | 			color: #2ecc71; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		.success-message h3 { | ||||||
|  | 			margin-top: 0; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		.success-message button { | ||||||
|  | 			background-color: #2ecc71; | ||||||
|  | 			color: white; | ||||||
|  | 			border: none; | ||||||
|  | 			border-radius: 4px; | ||||||
|  | 			padding: 0.75rem 1.5rem; | ||||||
|  | 			font-size: 1rem; | ||||||
|  | 			cursor: pointer; | ||||||
|  | 			margin-top: 1rem; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		.success-message button:hover { | ||||||
|  | 			background-color: #27ae60; | ||||||
|  | 		} | ||||||
|  | 	`), | ||||||
|  | ); | ||||||
							
								
								
									
										715
									
								
								docs/components/examples/case-studies/task-manager.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										715
									
								
								docs/components/examples/case-studies/task-manager.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,715 @@ | |||||||
|  | /** | ||||||
|  |  * Case Study: Task Manager Application | ||||||
|  |  * | ||||||
|  |  * This example demonstrates: | ||||||
|  |  * - Complex state management with signals | ||||||
|  |  * - Drag and drop functionality | ||||||
|  |  * - Local storage persistence | ||||||
|  |  * - Responsive design for different devices | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | import { el, on, dispatchEvent, scope } from "deka-dom-el"; | ||||||
|  | import { S } from "deka-dom-el/signals"; | ||||||
|  |  | ||||||
|  | /** @typedef {{ id: number, title: string, description: string, priority: string, status: string }} Task */ | ||||||
|  | /** | ||||||
|  |  * Task Manager Component | ||||||
|  |  * @returns {HTMLElement} Task manager UI | ||||||
|  |  */ | ||||||
|  | export function TaskManager() { | ||||||
|  | 	// <Tasks store> | ||||||
|  | 	const STORAGE_KEY = 'dde-task-manager'; | ||||||
|  | 	const STATUSES = { | ||||||
|  | 		TODO: 'todo', | ||||||
|  | 		IN_PROGRESS: 'in-progress', | ||||||
|  | 		DONE: 'done' | ||||||
|  | 	}; | ||||||
|  | 	/** @type {Task[]} */ | ||||||
|  | 	let initialTasks = []; | ||||||
|  | 	try { | ||||||
|  | 		const saved = localStorage.getItem(STORAGE_KEY); | ||||||
|  | 		if (saved) { | ||||||
|  | 			initialTasks = JSON.parse(saved); | ||||||
|  | 		} | ||||||
|  | 	} catch (e) { | ||||||
|  | 		console.error('Failed to load tasks from localStorage', e); | ||||||
|  | 	} | ||||||
|  | 	if (!initialTasks.length) { | ||||||
|  | 		initialTasks = [ | ||||||
|  | 			{ id: 1, title: 'Create project structure', description: 'Set up folders and initial files', | ||||||
|  | 				status: STATUSES.DONE, priority: 'high' }, | ||||||
|  | 			{ id: 2, title: 'Design UI components', description: 'Create mockups for main views', | ||||||
|  | 				status: STATUSES.IN_PROGRESS, priority: 'medium' }, | ||||||
|  | 			{ id: 3, title: 'Implement authentication', description: 'Set up user login and registration', | ||||||
|  | 				status: STATUSES.TODO, priority: 'high' }, | ||||||
|  | 			{ id: 4, title: 'Write documentation', description: 'Document API endpoints and usage examples', | ||||||
|  | 				status: STATUSES.TODO, priority: 'low' }, | ||||||
|  | 		]; | ||||||
|  | 	} | ||||||
|  | 	const tasks = S(initialTasks, { | ||||||
|  | 		add(task) { this.value.push(task); }, | ||||||
|  | 		remove(id) { this.value = this.value.filter(task => task.id !== id); }, | ||||||
|  | 		update(id, task) { | ||||||
|  | 			const current= this.value.find(t => t.id === id); | ||||||
|  | 			if (current) Object.assign(current, task); | ||||||
|  | 		} | ||||||
|  | 	}); | ||||||
|  | 	S.on(tasks, value => { | ||||||
|  | 		try { | ||||||
|  | 			localStorage.setItem(STORAGE_KEY, JSON.stringify(value)); | ||||||
|  | 		} catch (e) { | ||||||
|  | 			console.error('Failed to save tasks to localStorage', e); | ||||||
|  | 		} | ||||||
|  | 	}); | ||||||
|  | 	// </Tasks store> | ||||||
|  |  | ||||||
|  | 	const filterPriority = S('all'); | ||||||
|  | 	const searchQuery = S(''); | ||||||
|  | 	// Filtered tasks based on priority and search query | ||||||
|  | 	const filteredTasks = S(() => { | ||||||
|  | 		let filtered = tasks.get(); | ||||||
|  |  | ||||||
|  | 		// Filter by priority | ||||||
|  | 		if (filterPriority.get() !== 'all') { | ||||||
|  | 			filtered = filtered.filter(task => task.priority === filterPriority.get()); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		// Filter by search query | ||||||
|  | 		const query = searchQuery.get().toLowerCase(); | ||||||
|  | 		if (query) { | ||||||
|  | 			filtered = filtered.filter(task => | ||||||
|  | 				task.title.toLowerCase().includes(query) || | ||||||
|  | 				task.description.toLowerCase().includes(query) | ||||||
|  | 			); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		return filtered; | ||||||
|  | 	}); | ||||||
|  | 	/** Tasks grouped by status for display in columns */ | ||||||
|  | 	const tasksByStatus = S(() => { | ||||||
|  | 		const filtered = filteredTasks.get(); | ||||||
|  | 		return { | ||||||
|  | 			[STATUSES.TODO]: filtered.filter(t => t.status === STATUSES.TODO), | ||||||
|  | 			[STATUSES.IN_PROGRESS]: filtered.filter(t => t.status === STATUSES.IN_PROGRESS), | ||||||
|  | 			[STATUSES.DONE]: filtered.filter(t => t.status === STATUSES.DONE) | ||||||
|  | 		}; | ||||||
|  | 	}); | ||||||
|  |  | ||||||
|  | 	// <Add> signals and handlers for adding new tasks | ||||||
|  | 	const newTask = { title: '', description: '', priority: 'medium' }; | ||||||
|  | 	const onAddTask = e => { | ||||||
|  | 		e.preventDefault(); | ||||||
|  | 		if (!newTask.title) return; | ||||||
|  |  | ||||||
|  | 		S.action(tasks, "add", { | ||||||
|  | 			id: Date.now(), | ||||||
|  | 			status: STATUSES.TODO, | ||||||
|  | 			...newTask | ||||||
|  | 		}); | ||||||
|  | 		e.target.reset(); | ||||||
|  | 	}; | ||||||
|  | 	// </Add> | ||||||
|  | 	const onCardEdit= on("card:edit", /** @param {CardEditEvent} ev */({ detail: [ id, task ] })=> | ||||||
|  | 		S.action(tasks, "update", id, task)); | ||||||
|  | 	const onCardDelete= on("card:delete", /** @param {CardDeleteEvent} ev */({ detail: id })=> | ||||||
|  | 		S.action(tasks, "remove", id)); | ||||||
|  |  | ||||||
|  | 	const { onDragable, onDragArea }= moveElementAddon( | ||||||
|  | 		(id, status) => S.action(tasks, "update", id, { status }) | ||||||
|  | 	); | ||||||
|  |  | ||||||
|  | 	// Build the task manager UI | ||||||
|  | 	return el("div", { className: "task-manager" }).append( | ||||||
|  | 		el("header", { className: "app-header" }).append( | ||||||
|  | 			el("h1", "DDE Task Manager"), | ||||||
|  | 			el("div", { className: "app-controls" }).append( | ||||||
|  | 				el("input", { | ||||||
|  | 					type: "text", | ||||||
|  | 					placeholder: "Search tasks...", | ||||||
|  | 					value: searchQuery.get() | ||||||
|  | 				}, on("input", e => searchQuery.set(e.target.value))), | ||||||
|  | 				el("select", null, | ||||||
|  | 					on.defer(el=> el.value= filterPriority.get()), | ||||||
|  | 					on("change", e => filterPriority.set(e.target.value)) | ||||||
|  | 				).append( | ||||||
|  | 					el("option", { value: "all", textContent: "All Priorities" }), | ||||||
|  | 					el("option", { value: "low", textContent: "Low Priority" }), | ||||||
|  | 					el("option", { value: "medium", textContent: "Medium Priority" }), | ||||||
|  | 					el("option", { value: "high", textContent: "High Priority" }) | ||||||
|  | 				) | ||||||
|  | 			) | ||||||
|  | 		), | ||||||
|  |  | ||||||
|  | 		// Add new task form | ||||||
|  | 		el("form", { className: "new-task-form" }, on("submit", onAddTask)).append( | ||||||
|  | 			el("div", { className: "form-row" }).append( | ||||||
|  | 				el("input", { | ||||||
|  | 					type: "text", | ||||||
|  | 					placeholder: "New task title", | ||||||
|  | 					value: newTask.title, | ||||||
|  | 					required: true | ||||||
|  | 				}, on("input", e => newTask.title= e.target.value.trim())), | ||||||
|  | 				el("select", null, | ||||||
|  | 					on.defer(el=> el.value= newTask.priority), | ||||||
|  | 					on("change", e => newTask.priority= e.target.value) | ||||||
|  | 				).append( | ||||||
|  | 					el("option", { value: "low", textContent: "Low" }), | ||||||
|  | 					el("option", { value: "medium", textContent: "Medium" }), | ||||||
|  | 					el("option", { value: "high", textContent: "High" }) | ||||||
|  | 				), | ||||||
|  | 				el("button", { type: "submit", className: "add-btn" }).append("Add Task") | ||||||
|  | 			), | ||||||
|  | 			el("textarea", { | ||||||
|  | 				placeholder: "Task description (optional)", | ||||||
|  | 				value: newTask.description | ||||||
|  | 			}, on("input", e => newTask.description= e.target.value.trim())) | ||||||
|  | 		), | ||||||
|  |  | ||||||
|  | 		// Task board with columns | ||||||
|  | 		el("div", { className: "task-board" }).append( | ||||||
|  | 			// Todo column | ||||||
|  | 			el("div", { | ||||||
|  | 				id: `column-${STATUSES.TODO}`, | ||||||
|  | 				className: "task-column" | ||||||
|  | 			}, onDragArea(STATUSES.TODO)).append( | ||||||
|  | 				el("h2", { className: "column-header" }).append( | ||||||
|  | 					"To Do ", | ||||||
|  | 					el("span", { | ||||||
|  | 						textContent: S(() => tasksByStatus.get()[STATUSES.TODO].length), | ||||||
|  | 						className: "task-count" | ||||||
|  | 					}), | ||||||
|  | 				), | ||||||
|  | 				S.el(S(() => tasksByStatus.get()[STATUSES.TODO]), tasks => | ||||||
|  | 					el("div", { className: "column-tasks" }).append( | ||||||
|  | 						...tasks.map(task=> el(TaskCard, { task, onDragable }, onCardEdit, onCardDelete)) | ||||||
|  | 					) | ||||||
|  | 				) | ||||||
|  | 			), | ||||||
|  |  | ||||||
|  | 			// In Progress column | ||||||
|  | 			el("div", { | ||||||
|  | 				id: `column-${STATUSES.IN_PROGRESS}`, | ||||||
|  | 				className: "task-column" | ||||||
|  | 			}, onDragArea(STATUSES.IN_PROGRESS)).append( | ||||||
|  | 				el("h2", { className: "column-header" }).append( | ||||||
|  | 					"In Progress ", | ||||||
|  | 					el("span", { | ||||||
|  | 						textContent: S(() => tasksByStatus.get()[STATUSES.IN_PROGRESS].length), | ||||||
|  | 						className: "task-count", | ||||||
|  | 					}), | ||||||
|  | 				), | ||||||
|  | 				S.el(S(() => tasksByStatus.get()[STATUSES.IN_PROGRESS]), tasks => | ||||||
|  | 					el("div", { className: "column-tasks" }).append( | ||||||
|  | 						...tasks.map(task=> el(TaskCard, { task, onDragable }, onCardEdit, onCardDelete)) | ||||||
|  | 					) | ||||||
|  | 				) | ||||||
|  | 			), | ||||||
|  |  | ||||||
|  | 			// Done column | ||||||
|  | 			el("div", { | ||||||
|  | 				id: `column-${STATUSES.DONE}`, | ||||||
|  | 				className: "task-column" | ||||||
|  | 			}, onDragArea(STATUSES.DONE)).append( | ||||||
|  | 				el("h2", { className: "column-header" }).append( | ||||||
|  | 					"Done ", | ||||||
|  | 					el("span", { | ||||||
|  | 						textContent: S(() => tasksByStatus.get()[STATUSES.DONE].length), | ||||||
|  | 						className: "task-count", | ||||||
|  | 					}), | ||||||
|  | 				), | ||||||
|  | 				S.el(S(() => tasksByStatus.get()[STATUSES.DONE]), tasks => | ||||||
|  | 					el("div", { className: "column-tasks" }).append( | ||||||
|  | 						...tasks.map(task=> el(TaskCard, { task, onDragable }, onCardEdit, onCardDelete)) | ||||||
|  | 					) | ||||||
|  | 				) | ||||||
|  | 			) | ||||||
|  | 		), | ||||||
|  | 	); | ||||||
|  | } | ||||||
|  | /** @typedef {CustomEvent<[ string, Task ]>} CardEditEvent */ | ||||||
|  | /** @typedef {CustomEvent<string>} CardDeleteEvent */ | ||||||
|  | /** | ||||||
|  |  * Task Card Component | ||||||
|  |  * @type {(props: { task: Task, onDragable: (id: number) => ddeElementAddon<HTMLDivElement> }) => HTMLElement} | ||||||
|  |  * @fires {CardEditEvent} card:edit | ||||||
|  |  * @fires {CardDeleteEvent} card:delete | ||||||
|  |  * */ | ||||||
|  | function TaskCard({ task, onDragable }){ | ||||||
|  | 	const { host }= scope; | ||||||
|  | 	const isEditing = S(false); | ||||||
|  | 	const onEditStart = () => isEditing.set(true); | ||||||
|  |  | ||||||
|  | 	const dispatchEdit= dispatchEvent("card:edit", host); | ||||||
|  | 	const dispatchDelete= dispatchEvent("card:delete", host).bind(null, task.id); | ||||||
|  |  | ||||||
|  | 	return el("div", { | ||||||
|  | 		id: `task-${task.id}`, | ||||||
|  | 		className: `task-card priority-${task.priority}`, | ||||||
|  | 		draggable: true | ||||||
|  | 	}, onDragable(task.id)).append( | ||||||
|  | 		S.el(isEditing, editing => editing | ||||||
|  | 			? el(EditMode) | ||||||
|  | 			: el().append( | ||||||
|  | 				el("div", { className: "task-header" }).append( | ||||||
|  | 					el("h3", { className: "task-title", textContent: task.title }), | ||||||
|  | 					el("div", { className: "task-actions" }).append( | ||||||
|  | 						el("button", { | ||||||
|  | 							textContent: "✎", | ||||||
|  | 							className: "edit-btn", | ||||||
|  | 							ariaLabel: "Edit task" | ||||||
|  | 						}, on("click", onEditStart)), | ||||||
|  | 						el("button", { | ||||||
|  | 							textContent: "✕", | ||||||
|  | 							className: "delete-btn", | ||||||
|  | 							ariaLabel: "Delete task" | ||||||
|  | 						}, on("click", dispatchDelete)) | ||||||
|  | 					) | ||||||
|  | 				), | ||||||
|  | 				!task.description | ||||||
|  | 				? el() | ||||||
|  | 				: el("p", { className: "task-description", textContent: task.description }), | ||||||
|  | 				el("div", { className: "task-meta" }).append( | ||||||
|  | 					el("span", { | ||||||
|  | 						className: `priority-badge priority-${task.priority}`, | ||||||
|  | 						textContent: task.priority.charAt(0).toUpperCase() + task.priority.slice(1) | ||||||
|  | 					}) | ||||||
|  | 				) | ||||||
|  | 			) | ||||||
|  | 		) | ||||||
|  | 	); | ||||||
|  | 	function EditMode(){ | ||||||
|  | 		const onSubmit = on("submit", e => { | ||||||
|  | 			e.preventDefault(); | ||||||
|  | 			const formData = new FormData(/** @type {HTMLFormElement} */(e.target)); | ||||||
|  | 			const title = formData.get("title"); | ||||||
|  | 			const description = formData.get("description"); | ||||||
|  | 			const priority = formData.get("priority"); | ||||||
|  | 			isEditing.set(false); | ||||||
|  | 			dispatchEdit([ task.id, { title, description, priority } ]); | ||||||
|  | 		}) | ||||||
|  | 		const onEditCancel = () => isEditing.set(false); | ||||||
|  |  | ||||||
|  | 		return el("form", { className: "task-edit-form" }, onSubmit).append( | ||||||
|  | 			el("input", { | ||||||
|  | 				name: "title", | ||||||
|  | 				className: "task-title-input", | ||||||
|  | 				defaultValue: task.title, | ||||||
|  | 				placeholder: "Task title", | ||||||
|  | 				required: true, | ||||||
|  | 				autoFocus: true | ||||||
|  | 			}), | ||||||
|  | 			el("textarea", { | ||||||
|  | 				name: "description", | ||||||
|  | 				className: "task-desc-input", | ||||||
|  | 				defaultValue: task.description, | ||||||
|  | 				placeholder: "Description (optional)" | ||||||
|  | 			}), | ||||||
|  | 			el("select", { | ||||||
|  | 				name: "priority", | ||||||
|  | 			}, on.defer(el=> el.value = task.priority)).append( | ||||||
|  | 				el("option", { value: "low", textContent: "Low Priority" }), | ||||||
|  | 				el("option", { value: "medium", textContent: "Medium Priority" }), | ||||||
|  | 				el("option", { value: "high", textContent: "High Priority" }) | ||||||
|  | 			), | ||||||
|  | 			el("div", { className: "task-edit-actions" }).append( | ||||||
|  | 				el("button", { | ||||||
|  | 					textContent: "Cancel", | ||||||
|  | 					type: "button", | ||||||
|  | 					className: "cancel-btn" | ||||||
|  | 				}, on("click", onEditCancel)), | ||||||
|  | 				el("button", { | ||||||
|  | 					textContent: "Save", | ||||||
|  | 					type: "submit", | ||||||
|  | 					className: "save-btn" | ||||||
|  | 				}) | ||||||
|  | 			) | ||||||
|  | 		); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Helper function to handle move an element | ||||||
|  |  * @param {(id: string, status: string) => void} onMoved | ||||||
|  |  * */ | ||||||
|  | function moveElementAddon(onMoved){ | ||||||
|  | 	let draggedTaskId = null; | ||||||
|  | 	function onDragable(id) { | ||||||
|  | 		return element => { | ||||||
|  | 			on("dragstart", e => { | ||||||
|  | 				draggedTaskId= id; | ||||||
|  | 				e.dataTransfer.effectAllowed = 'move'; | ||||||
|  |  | ||||||
|  | 				// Add some styling to the element being dragged | ||||||
|  | 				setTimeout(() => { | ||||||
|  | 					const el = document.getElementById(`task-${id}`); | ||||||
|  | 					if (el) el.classList.add('dragging'); | ||||||
|  | 				}, 0); | ||||||
|  | 			})(element); | ||||||
|  |  | ||||||
|  | 			on("dragend", () => { | ||||||
|  | 				draggedTaskId= null; | ||||||
|  |  | ||||||
|  | 				// Remove the styling | ||||||
|  | 				const el = document.getElementById(`task-${id}`); | ||||||
|  | 				if (el) el.classList.remove('dragging'); | ||||||
|  | 			})(element); | ||||||
|  | 		}; | ||||||
|  | 	} | ||||||
|  | 	function onDragArea(status) { | ||||||
|  | 		return element => { | ||||||
|  | 			on("dragover", e => { | ||||||
|  | 				e.preventDefault(); | ||||||
|  | 				e.dataTransfer.dropEffect = 'move'; | ||||||
|  |  | ||||||
|  | 				// Add a visual indicator for the drop target | ||||||
|  | 				const column = document.getElementById(`column-${status}`); | ||||||
|  | 				if (column) column.classList.add('drag-over'); | ||||||
|  | 			})(element); | ||||||
|  |  | ||||||
|  | 			on("dragleave", () => { | ||||||
|  | 				// Remove the visual indicator | ||||||
|  | 				const column = document.getElementById(`column-${status}`); | ||||||
|  | 				if (column) column.classList.remove('drag-over'); | ||||||
|  | 			})(element); | ||||||
|  |  | ||||||
|  | 			on("drop", e => { | ||||||
|  | 				e.preventDefault(); | ||||||
|  | 				const id = draggedTaskId; | ||||||
|  | 				if (id) onMoved(id, status); | ||||||
|  | 				// Remove the visual indicator | ||||||
|  | 				const column = document.getElementById(`column-${status}`); | ||||||
|  | 				if (column) column.classList.remove('drag-over'); | ||||||
|  | 			})(element); | ||||||
|  | 		}; | ||||||
|  | 	} | ||||||
|  | 	return { onDragable, onDragArea }; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Render the component | ||||||
|  | document.body.append( | ||||||
|  | 	el("div", { style: "padding: 20px; background: #f5f5f5; min-height: 100vh;" }).append( | ||||||
|  | 		el(TaskManager) | ||||||
|  | 	), | ||||||
|  | 	el("style", ` | ||||||
|  | 		.task-manager { | ||||||
|  | 			font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; | ||||||
|  | 			max-width: 1200px; | ||||||
|  | 			margin: 0 auto; | ||||||
|  | 			padding: 1rem; | ||||||
|  | 			color: #333; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		.app-header { | ||||||
|  | 			display: flex; | ||||||
|  | 			justify-content: space-between; | ||||||
|  | 			align-items: center; | ||||||
|  | 			margin-bottom: 1.5rem; | ||||||
|  | 			flex-wrap: wrap; | ||||||
|  | 			gap: 1rem; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		.app-header h1 { | ||||||
|  | 			margin: 0; | ||||||
|  | 			color: #2d3748; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		.app-controls { | ||||||
|  | 			display: flex; | ||||||
|  | 			gap: 1rem; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		.app-controls input, | ||||||
|  | 		.app-controls select { | ||||||
|  | 			padding: 0.5rem; | ||||||
|  | 			border: 1px solid #e2e8f0; | ||||||
|  | 			border-radius: 4px; | ||||||
|  | 			font-size: 0.9rem; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		.new-task-form { | ||||||
|  | 			background: white; | ||||||
|  | 			padding: 1.5rem; | ||||||
|  | 			border-radius: 8px; | ||||||
|  | 			box-shadow: 0 2px 10px rgba(0, 0, 0, 0.05); | ||||||
|  | 			margin-bottom: 2rem; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		.form-row { | ||||||
|  | 			display: flex; | ||||||
|  | 			gap: 1rem; | ||||||
|  | 			margin-bottom: 1rem; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		.form-row input { | ||||||
|  | 			flex-grow: 1; | ||||||
|  | 			padding: 0.75rem; | ||||||
|  | 			border: 1px solid #e2e8f0; | ||||||
|  | 			border-radius: 4px; | ||||||
|  | 			font-size: 1rem; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		.form-row select { | ||||||
|  | 			width: 100px; | ||||||
|  | 			padding: 0.75rem; | ||||||
|  | 			border: 1px solid #e2e8f0; | ||||||
|  | 			border-radius: 4px; | ||||||
|  | 			font-size: 1rem; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		.add-btn { | ||||||
|  | 			background: #4a90e2; | ||||||
|  | 			color: white; | ||||||
|  | 			border: none; | ||||||
|  | 			border-radius: 4px; | ||||||
|  | 			padding: 0.75rem 1.5rem; | ||||||
|  | 			font-size: 1rem; | ||||||
|  | 			cursor: pointer; | ||||||
|  | 			transition: background 0.2s ease; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		.add-btn:hover { | ||||||
|  | 			background: #3a7bc8; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		.new-task-form textarea { | ||||||
|  | 			width: 100%; | ||||||
|  | 			padding: 0.75rem; | ||||||
|  | 			border: 1px solid #e2e8f0; | ||||||
|  | 			border-radius: 4px; | ||||||
|  | 			font-size: 1rem; | ||||||
|  | 			resize: vertical; | ||||||
|  | 			min-height: 80px; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		.task-board { | ||||||
|  | 			display: grid; | ||||||
|  | 			grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); | ||||||
|  | 			gap: 1.5rem; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		.task-column { | ||||||
|  | 			background: #f7fafc; | ||||||
|  | 			border-radius: 8px; | ||||||
|  | 			padding: 1rem; | ||||||
|  | 			min-height: 400px; | ||||||
|  | 			transition: background 0.2s ease; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		.column-header { | ||||||
|  | 			margin-top: 0; | ||||||
|  | 			padding-bottom: 0.75rem; | ||||||
|  | 			border-bottom: 2px solid #e2e8f0; | ||||||
|  | 			font-size: 1.25rem; | ||||||
|  | 			color: #2d3748; | ||||||
|  | 			display: flex; | ||||||
|  | 			align-items: center; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		.task-count { | ||||||
|  | 			display: inline-flex; | ||||||
|  | 			justify-content: center; | ||||||
|  | 			align-items: center; | ||||||
|  | 			background: #e2e8f0; | ||||||
|  | 			color: #4a5568; | ||||||
|  | 			border-radius: 50%; | ||||||
|  | 			width: 25px; | ||||||
|  | 			height: 25px; | ||||||
|  | 			font-size: 0.875rem; | ||||||
|  | 			margin-left: 0.5rem; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		.column-tasks { | ||||||
|  | 			margin-top: 1rem; | ||||||
|  | 			display: flex; | ||||||
|  | 			flex-direction: column; | ||||||
|  | 			gap: 1rem; | ||||||
|  | 			min-height: 200px; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		.task-card { | ||||||
|  | 			background: white; | ||||||
|  | 			border-radius: 6px; | ||||||
|  | 			padding: 1rem; | ||||||
|  | 			box-shadow: 0 2px 5px rgba(0, 0, 0, 0.05); | ||||||
|  | 			cursor: grab; | ||||||
|  | 			transition: transform 0.2s ease, box-shadow 0.2s ease; | ||||||
|  | 			position: relative; | ||||||
|  | 			border-left: 4px solid #ccc; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		.task-card:hover { | ||||||
|  | 			transform: translateY(-3px); | ||||||
|  | 			box-shadow: 0 5px 10px rgba(0, 0, 0, 0.1); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		.task-card.dragging { | ||||||
|  | 			opacity: 0.5; | ||||||
|  | 			cursor: grabbing; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		.task-card.priority-low { | ||||||
|  | 			border-left-color: #38b2ac; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		.task-card.priority-medium { | ||||||
|  | 			border-left-color: #ecc94b; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		.task-card.priority-high { | ||||||
|  | 			border-left-color: #e53e3e; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		.task-header { | ||||||
|  | 			display: flex; | ||||||
|  | 			justify-content: space-between; | ||||||
|  | 			align-items: flex-start; | ||||||
|  | 			margin-bottom: 0.5rem; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		.task-title { | ||||||
|  | 			margin: 0; | ||||||
|  | 			font-size: 1.1rem; | ||||||
|  | 			color: #2d3748; | ||||||
|  | 			word-break: break-word; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		.task-description { | ||||||
|  | 			margin: 0.5rem 0; | ||||||
|  | 			font-size: 0.9rem; | ||||||
|  | 			color: #4a5568; | ||||||
|  | 			word-break: break-word; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		.task-actions { | ||||||
|  | 			display: flex; | ||||||
|  | 			gap: 0.5rem; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		.edit-btn, | ||||||
|  | 		.delete-btn { | ||||||
|  | 			background: none; | ||||||
|  | 			border: none; | ||||||
|  | 			font-size: 1rem; | ||||||
|  | 			cursor: pointer; | ||||||
|  | 			width: 24px; | ||||||
|  | 			height: 24px; | ||||||
|  | 			display: inline-flex; | ||||||
|  | 			justify-content: center; | ||||||
|  | 			align-items: center; | ||||||
|  | 			border-radius: 50%; | ||||||
|  | 			color: #718096; | ||||||
|  | 			transition: background 0.2s ease, color 0.2s ease; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		.edit-btn:hover { | ||||||
|  | 			background: #edf2f7; | ||||||
|  | 			color: #4a5568; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		.delete-btn:hover { | ||||||
|  | 			background: #fed7d7; | ||||||
|  | 			color: #e53e3e; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		.task-meta { | ||||||
|  | 			display: flex; | ||||||
|  | 			justify-content: space-between; | ||||||
|  | 			align-items: center; | ||||||
|  | 			margin-top: 0.75rem; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		.priority-badge { | ||||||
|  | 			font-size: 0.75rem; | ||||||
|  | 			padding: 0.2rem 0.5rem; | ||||||
|  | 			border-radius: 4px; | ||||||
|  | 			font-weight: 500; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		.priority-badge.priority-low { | ||||||
|  | 			background: #e6fffa; | ||||||
|  | 			color: #2c7a7b; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		.priority-badge.priority-medium { | ||||||
|  | 			background: #fefcbf; | ||||||
|  | 			color: #975a16; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		.priority-badge.priority-high { | ||||||
|  | 			background: #fed7d7; | ||||||
|  | 			color: #c53030; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		.drag-over { | ||||||
|  | 			background: #f0f9ff; | ||||||
|  | 			border: 2px dashed #4a90e2; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		.task-edit-form { | ||||||
|  | 			display: flex; | ||||||
|  | 			flex-direction: column; | ||||||
|  | 			gap: 0.75rem; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		.task-title-input, | ||||||
|  | 		.task-desc-input { | ||||||
|  | 			width: 100%; | ||||||
|  | 			padding: 0.5rem; | ||||||
|  | 			border: 1px solid #e2e8f0; | ||||||
|  | 			border-radius: 4px; | ||||||
|  | 			font-size: 0.9rem; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		.task-desc-input { | ||||||
|  | 			min-height: 60px; | ||||||
|  | 			resize: vertical; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		.task-edit-actions { | ||||||
|  | 			display: flex; | ||||||
|  | 			justify-content: flex-end; | ||||||
|  | 			gap: 0.5rem; | ||||||
|  | 			margin-top: 0.5rem; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		.cancel-btn, | ||||||
|  | 		.save-btn { | ||||||
|  | 			padding: 0.4rem 0.75rem; | ||||||
|  | 			border-radius: 4px; | ||||||
|  | 			font-size: 0.9rem; | ||||||
|  | 			cursor: pointer; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		.cancel-btn { | ||||||
|  | 			background: #edf2f7; | ||||||
|  | 			color: #4a5568; | ||||||
|  | 			border: 1px solid #e2e8f0; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		.save-btn { | ||||||
|  | 			background: #4a90e2; | ||||||
|  | 			color: white; | ||||||
|  | 			border: none; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		@media (max-width: 768px) { | ||||||
|  | 			.app-header { | ||||||
|  | 				flex-direction: column; | ||||||
|  | 				align-items: flex-start; | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			.app-controls { | ||||||
|  | 				width: 100%; | ||||||
|  | 				flex-direction: column; | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			.form-row { | ||||||
|  | 				flex-direction: column; | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			.task-board { | ||||||
|  | 				grid-template-columns: 1fr; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	`) | ||||||
|  | ); | ||||||
| @@ -0,0 +1,23 @@ | |||||||
|  | import { customElementWithDDE, el, on } from "deka-dom-el"; | ||||||
|  | export class HTMLCustomElement extends HTMLElement{ | ||||||
|  | 	static tagName= "custom-element"; | ||||||
|  | 	connectedCallback(){ | ||||||
|  | 		this.append( | ||||||
|  | 			el("p", "Hello from custom element!") | ||||||
|  | 		); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | customElementWithDDE(HTMLCustomElement); | ||||||
|  | customElements.define(HTMLCustomElement.tagName, HTMLCustomElement); | ||||||
|  |  | ||||||
|  | const instance= el(HTMLCustomElement.tagName); | ||||||
|  | on.connected( // preffered | ||||||
|  | 	e=> console.log("Element connected to the DOM (v1):", e) | ||||||
|  | )(instance); | ||||||
|  | instance.addEventListener( | ||||||
|  | 	"dde:connected", | ||||||
|  | 	e=> console.log("Element connected to the DOM (v2):", e) | ||||||
|  | ); | ||||||
|  | document.body.append( | ||||||
|  | 	instance, | ||||||
|  | ); | ||||||
							
								
								
									
										33
									
								
								docs/components/examples/customElement/dde.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								docs/components/examples/customElement/dde.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,33 @@ | |||||||
|  | import { | ||||||
|  | 	customElementRender, | ||||||
|  | 	customElementWithDDE, | ||||||
|  | } from "deka-dom-el"; | ||||||
|  | export class HTMLCustomElement extends HTMLElement{ | ||||||
|  | 	static tagName= "custom-element"; | ||||||
|  | 	static observedAttributes= [ "attr" ]; | ||||||
|  | 	connectedCallback(){ | ||||||
|  | 		customElementRender( | ||||||
|  | 			this.attachShadow({ mode: "open" }), | ||||||
|  | 			ddeComponent, | ||||||
|  | 			this | ||||||
|  | 		); | ||||||
|  | 	} | ||||||
|  | 	set attr(value){ this.setAttribute("attr", value); } | ||||||
|  | 	get attr(){ return this.getAttribute("attr"); } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | import { el, on, scope } from "deka-dom-el"; | ||||||
|  | function ddeComponent({ attr }){ | ||||||
|  | 	scope.host( | ||||||
|  | 		on.connected(e=> console.log(e.target.outerHTML)), | ||||||
|  | 	); | ||||||
|  | 	return el().append( | ||||||
|  | 		el("p", `Hello from Custom Element with attribute '${attr}'`) | ||||||
|  | 	); | ||||||
|  | } | ||||||
|  | customElementWithDDE(HTMLCustomElement); | ||||||
|  | customElements.define(HTMLCustomElement.tagName, HTMLCustomElement); | ||||||
|  |  | ||||||
|  | document.body.append( | ||||||
|  | 	el(HTMLCustomElement.tagName, { attr: "Attribute" }) | ||||||
|  | ); | ||||||
| @@ -2,7 +2,6 @@ | |||||||
| import { | import { | ||||||
| 	customElementRender, | 	customElementRender, | ||||||
| 	customElementWithDDE, | 	customElementWithDDE, | ||||||
| 	observedAttributes, |  | ||||||
| } from "deka-dom-el"; | } from "deka-dom-el"; | ||||||
| /** @type {ddePublicElementTagNameMap} */ | /** @type {ddePublicElementTagNameMap} */ | ||||||
| import { S } from "deka-dom-el/signals"; | import { S } from "deka-dom-el/signals"; | ||||||
| @@ -1,5 +1,5 @@ | |||||||
| class CustomHTMLElement extends HTMLElement{ | export class HTMLCustomElement extends HTMLElement{ | ||||||
| 	static tagName = "custom-element"; // just suggestion, we can use `el(CustomHTMLElement.tagName)`
 | 	static tagName= "custom-element"; // just suggestion, we can use `el(HTMLCustomElement.tagName)`
 | ||||||
| 	static observedAttributes= [ "custom-attribute" ]; | 	static observedAttributes= [ "custom-attribute" ]; | ||||||
| 	constructor(){ | 	constructor(){ | ||||||
| 		super(); | 		super(); | ||||||
| @@ -9,7 +9,7 @@ class CustomHTMLElement extends HTMLElement{ | |||||||
| 		// nice place to render custom element
 | 		// nice place to render custom element
 | ||||||
| 	} | 	} | ||||||
| 	attributeChangedCallback(name, oldValue, newValue){ | 	attributeChangedCallback(name, oldValue, newValue){ | ||||||
| 		// listen to attribute changes (see `observedAttributes`)
 | 		// listen to attribute changes (see `S.observedAttributes`)
 | ||||||
| 	} | 	} | ||||||
| 	disconnectedCallback(){ | 	disconnectedCallback(){ | ||||||
| 		// nice place to clean up
 | 		// nice place to clean up
 | ||||||
| @@ -18,4 +18,4 @@ class CustomHTMLElement extends HTMLElement{ | |||||||
| 	get customAttribute(){ return this.getAttribute("custom-attribute"); } | 	get customAttribute(){ return this.getAttribute("custom-attribute"); } | ||||||
| 	set customAttribute(value){ this.setAttribute("custom-attribute", value); } | 	set customAttribute(value){ this.setAttribute("custom-attribute", value); } | ||||||
| } | } | ||||||
| customElements.define(CustomHTMLElement.tagName, CustomHTMLElement); | customElements.define(HTMLCustomElement.tagName, HTMLCustomElement); | ||||||
							
								
								
									
										39
									
								
								docs/components/examples/customElement/observedAttributes.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								docs/components/examples/customElement/observedAttributes.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,39 @@ | |||||||
|  | import { | ||||||
|  | 	customElementRender, | ||||||
|  | 	customElementWithDDE, | ||||||
|  | 	el, on, scope, | ||||||
|  | } from "deka-dom-el"; | ||||||
|  | import { S } from "deka-dom-el/signals"; | ||||||
|  | export class HTMLCustomElement extends HTMLElement{ | ||||||
|  | 	static tagName= "custom-element"; | ||||||
|  | 	static observedAttributes= [ "attr" ]; | ||||||
|  | 	connectedCallback(){ | ||||||
|  | 		customElementRender( | ||||||
|  | 			this.attachShadow({ mode: "open" }), | ||||||
|  | 			ddeComponent, | ||||||
|  | 			S.observedAttributes | ||||||
|  | 		); | ||||||
|  | 	} | ||||||
|  | 	set attr(value){ this.setAttribute("attr", value); } | ||||||
|  | 	get attr(){ return this.getAttribute("attr"); } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /** @param {{ attr: ddeSignal<string, {}> }} props */ | ||||||
|  | function ddeComponent({ attr }){ | ||||||
|  | 	scope.host( | ||||||
|  | 		on.connected(e=> console.log(( /** @type {HTMLParagraphElement} */ (e.target)).outerHTML)), | ||||||
|  | 	); | ||||||
|  | 	return el().append( | ||||||
|  | 		el("p", S(()=> `Hello from Custom Element with attribute '${attr.get()}'`)) | ||||||
|  | 	); | ||||||
|  | } | ||||||
|  | customElementWithDDE(HTMLCustomElement); | ||||||
|  | customElements.define(HTMLCustomElement.tagName, HTMLCustomElement); | ||||||
|  |  | ||||||
|  | document.body.append( | ||||||
|  | 	el(HTMLCustomElement.tagName, { attr: "Attribute" }) | ||||||
|  | ); | ||||||
|  | setTimeout( | ||||||
|  | 	()=> document.querySelector(HTMLCustomElement.tagName).setAttribute("attr", "New Value"), | ||||||
|  | 	3*750 | ||||||
|  | ); | ||||||
							
								
								
									
										63
									
								
								docs/components/examples/customElement/shadowRoot.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								docs/components/examples/customElement/shadowRoot.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,63 @@ | |||||||
|  | import { | ||||||
|  | 	el, | ||||||
|  | 	customElementRender, | ||||||
|  | 	customElementWithDDE, | ||||||
|  | } from "deka-dom-el"; | ||||||
|  | function ddeComponent(){ | ||||||
|  | 	return el().append( | ||||||
|  | 		el("style", ` | ||||||
|  | 			.red{ color: firebrick; } | ||||||
|  | 		`), | ||||||
|  | 		el("p", { className: "red" }).append( | ||||||
|  | 			"Hello from ", el("slot", "Custom Element"), "!" | ||||||
|  | 		) | ||||||
|  | 	); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | export class A extends HTMLElement{ | ||||||
|  | 	static tagName= "custom-element-without"; | ||||||
|  | 	connectedCallback(){ | ||||||
|  | 		customElementRender(this, ddeComponent); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | customElementWithDDE(A); | ||||||
|  | customElements.define(A.tagName, A); | ||||||
|  | export class B extends HTMLElement{ | ||||||
|  | 	static tagName= "custom-element-open"; | ||||||
|  | 	connectedCallback(){ | ||||||
|  | 		customElementRender( | ||||||
|  | 			this.attachShadow({ mode: "open" }), | ||||||
|  | 			ddeComponent | ||||||
|  | 		); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | customElementWithDDE(B); | ||||||
|  | customElements.define(B.tagName, B); | ||||||
|  | export class C extends HTMLElement{ | ||||||
|  | 	static tagName= "custom-element-closed"; | ||||||
|  | 	connectedCallback(){ | ||||||
|  | 		customElementRender( | ||||||
|  | 			this.attachShadow({ mode: "closed" }), | ||||||
|  | 			ddeComponent | ||||||
|  | 		); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | customElementWithDDE(C); | ||||||
|  | customElements.define(C.tagName, C); | ||||||
|  |  | ||||||
|  | document.body.append( | ||||||
|  | 	el(A.tagName).append("Without shadowRoot"), | ||||||
|  | 	el("hr"), | ||||||
|  | 	el(B.tagName).append("Open shadowRoot"), | ||||||
|  | 	el("hr"), | ||||||
|  | 	el(C.tagName).append("Closed shadowRoot"), | ||||||
|  | 	el("style", ` | ||||||
|  | 		.red{ color: crimson; } | ||||||
|  | 	`), | ||||||
|  | ); | ||||||
|  | console.log(A.tagName, "expect modifications"); | ||||||
|  | document.body.querySelector(A.tagName).querySelector("p").textContent+= " (editable with JS)"; | ||||||
|  | console.log(B.tagName, "expect modifications"); | ||||||
|  | document.body.querySelector(B.tagName).shadowRoot.querySelector("p").textContent+= " (editable with JS)"; | ||||||
|  | console.log(C.tagName, "expect error ↓"); | ||||||
|  | document.body.querySelector(C.tagName).querySelector("p").textContent+= " (editable with JS)"; | ||||||
							
								
								
									
										41
									
								
								docs/components/examples/customElement/simulateSlots.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								docs/components/examples/customElement/simulateSlots.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,41 @@ | |||||||
|  | import { | ||||||
|  | 	customElementRender, | ||||||
|  | 	customElementWithDDE, | ||||||
|  | 	el, | ||||||
|  | 	simulateSlots | ||||||
|  | } from "deka-dom-el"; | ||||||
|  | export class HTMLCustomElement extends HTMLElement{ | ||||||
|  | 	static tagName= "custom-slotting"; | ||||||
|  | 	connectedCallback(){ | ||||||
|  | 		const c= ()=> simulateSlots(this, ddeComponent()); | ||||||
|  | 		customElementRender(this, c); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | customElementWithDDE(HTMLCustomElement); | ||||||
|  | customElements.define(HTMLCustomElement.tagName, HTMLCustomElement); | ||||||
|  |  | ||||||
|  | document.body.append( | ||||||
|  | 	el(HTMLCustomElement.tagName), | ||||||
|  | 	el(HTMLCustomElement.tagName).append( | ||||||
|  | 		"Slot" | ||||||
|  | 	), | ||||||
|  | 	el(ddeComponentSlot), | ||||||
|  | 	el(ddeComponentSlot).append( | ||||||
|  | 		"Slot" | ||||||
|  | 	), | ||||||
|  | ); | ||||||
|  |  | ||||||
|  | function ddeComponent(){ | ||||||
|  | 	return el().append( | ||||||
|  | 		el("p").append( | ||||||
|  | 			"Hello ", el("slot", "World") | ||||||
|  | 		) | ||||||
|  | 	); | ||||||
|  | } | ||||||
|  | function ddeComponentSlot(){ | ||||||
|  | 	return simulateSlots(el().append( | ||||||
|  | 		el("p").append( | ||||||
|  | 			"Hello ", el("slot", "World") | ||||||
|  | 		) | ||||||
|  | 	)); | ||||||
|  | } | ||||||
							
								
								
									
										15
									
								
								docs/components/examples/debugging/consoleLog.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								docs/components/examples/debugging/consoleLog.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,15 @@ | |||||||
|  | // Debugging a (derived) signal with `console.log` | ||||||
|  | import { S } from "deka-dom-el/signals"; | ||||||
|  | const name= S("Alice"); | ||||||
|  | const greeting = S(() => { | ||||||
|  | 	// log derived signals | ||||||
|  | 	const log = "Hello, " + name.get(); | ||||||
|  | 	console.log(log); | ||||||
|  | 	console.log(name.valueOf()); | ||||||
|  | 	return log; | ||||||
|  | }); | ||||||
|  |  | ||||||
|  | // log signals in general | ||||||
|  | S.on(greeting, value => console.log("Greeting changed to:", value)); | ||||||
|  |  | ||||||
|  | name.set("Bob"); // Should trigger computation and listener`) | ||||||
							
								
								
									
										67
									
								
								docs/components/examples/debugging/debouncing.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										67
									
								
								docs/components/examples/debugging/debouncing.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,67 @@ | |||||||
|  | import { S } from "deka-dom-el/signals"; | ||||||
|  |  | ||||||
|  | // ===== Approach 1: Traditional debouncing with utility function ===== | ||||||
|  | function debounce(func, wait) { | ||||||
|  | 	let timeout; | ||||||
|  | 	return (...args)=> { | ||||||
|  | 		clearTimeout(timeout); | ||||||
|  | 		timeout= setTimeout(() => func(...args), wait); | ||||||
|  | 	}; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | const inputSignal = S(""); | ||||||
|  | const debouncedSet = debounce(value => inputSignal.set(value), 300); | ||||||
|  |  | ||||||
|  | // In your input handler | ||||||
|  | inputElement.addEventListener("input", e => debouncedSet(e.target.value)); | ||||||
|  |  | ||||||
|  | // ===== Approach 2: Signal debouncing utility ===== | ||||||
|  | /** | ||||||
|  |  * Creates a debounced signal that only updates after delay | ||||||
|  |  * @param {any} initialValue Initial signal value | ||||||
|  |  * @param {number} delay Debounce delay in ms | ||||||
|  |  */ | ||||||
|  | function createDebouncedSignal(initialValue, delay = 300) { | ||||||
|  | 	// Create two signals: one for immediate updates, one for debounced values | ||||||
|  | 	const immediateSignal = S(initialValue); | ||||||
|  | 	const debouncedSignal = S(initialValue); | ||||||
|  |  | ||||||
|  | 	// Keep track of the timeout | ||||||
|  | 	let timeout = null; | ||||||
|  |  | ||||||
|  | 	// Set up a listener on the immediate signal | ||||||
|  | 	S.on(immediateSignal, value => { | ||||||
|  | 		// Clear any existing timeout | ||||||
|  | 		if (timeout) clearTimeout(timeout); | ||||||
|  |  | ||||||
|  | 		// Set a new timeout to update the debounced signal | ||||||
|  | 		timeout = setTimeout(() => { | ||||||
|  | 			debouncedSignal.set(value); | ||||||
|  | 		}, delay); | ||||||
|  | 	}); | ||||||
|  |  | ||||||
|  | 	// Return an object with both signals and a setter function | ||||||
|  | 	return { | ||||||
|  | 		// The raw signal that updates immediately | ||||||
|  | 		raw: immediateSignal, | ||||||
|  | 		// The debounced signal that only updates after delay | ||||||
|  | 		debounced: debouncedSignal, | ||||||
|  | 		// Setter function to update the immediate signal | ||||||
|  | 		set: value => immediateSignal.set(value) | ||||||
|  | 	}; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Usage example | ||||||
|  | const searchInput = createDebouncedSignal("", 300); | ||||||
|  |  | ||||||
|  | // Log immediate changes for demonstration | ||||||
|  | S.on(searchInput.raw, value => console.log("Input changed to:", value)); | ||||||
|  |  | ||||||
|  | // Only perform expensive operations on the debounced value | ||||||
|  | S.on(searchInput.debounced, value => { | ||||||
|  | 	console.log("Performing search with:", value); | ||||||
|  | 	// Expensive operation would go here | ||||||
|  | }); | ||||||
|  |  | ||||||
|  | // In your input handler | ||||||
|  | searchElement.addEventListener("input", e => searchInput.set(e.target.value)); | ||||||
| @@ -0,0 +1,4 @@ | |||||||
|  | // Example of reactive element marker | ||||||
|  | <!--<dde:mark type="reactive" component="<component-name>">--> | ||||||
|  | <!-- content that updates when signal changes --> | ||||||
|  | <!--</dde:mark>--> | ||||||
							
								
								
									
										15
									
								
								docs/components/examples/debugging/mutations.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								docs/components/examples/debugging/mutations.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,15 @@ | |||||||
|  | import { S } from "deka-dom-el/signals"; | ||||||
|  | // Wrong - direct mutation doesn't trigger updates | ||||||
|  | const todos1 = S([{ text: "Learn signals", completed: false }]); | ||||||
|  | todos1.get().push({ text: "Debug signals", completed: false }); // Won't trigger updates! | ||||||
|  |  | ||||||
|  | // Correct - using .set() with a new array | ||||||
|  | todos1.set([...todos1.get(), { text: "Debug signals", completed: false }]); | ||||||
|  |  | ||||||
|  | // Better - using actions | ||||||
|  | const todos2 = S([], { | ||||||
|  | 	add(text) { | ||||||
|  | 		this.value.push({ text, completed: false }); | ||||||
|  | 	} | ||||||
|  | }); | ||||||
|  | S.action(todos2, "add", "Debug signals"); | ||||||
							
								
								
									
										14
									
								
								docs/components/examples/elements/dde-dom-create.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								docs/components/examples/elements/dde-dom-create.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,14 @@ | |||||||
|  | import { el } from "deka-dom-el"; | ||||||
|  |  | ||||||
|  | // Create element with properties | ||||||
|  | const button = el("button", { | ||||||
|  | 	textContent: "Click me", | ||||||
|  | 	className: "primary", | ||||||
|  | 	disabled: true | ||||||
|  | }); | ||||||
|  |  | ||||||
|  | // Shorter and more expressive | ||||||
|  | // than the native approach | ||||||
|  |  | ||||||
|  | // Add to DOM | ||||||
|  | document.body.append(button); | ||||||
							
								
								
									
										11
									
								
								docs/components/examples/elements/dde-dom-tree.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								docs/components/examples/elements/dde-dom-tree.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | |||||||
|  | import { el } from "deka-dom-el"; | ||||||
|  |  | ||||||
|  | // Chainable, natural nesting | ||||||
|  | // append() returns parent element | ||||||
|  | // making chains easy and intuitive | ||||||
|  | document.body.append( | ||||||
|  | 	el("div").append( | ||||||
|  | 		el("h1", "Title"), | ||||||
|  | 		el("p", "Paragraph") | ||||||
|  | 	) | ||||||
|  | ); | ||||||
| @@ -24,7 +24,11 @@ document.body.append( | |||||||
| ); | ); | ||||||
| 
 | 
 | ||||||
| import { chainableAppend } from "deka-dom-el"; | import { chainableAppend } from "deka-dom-el"; | ||||||
| /** @param {keyof HTMLElementTagNameMap} tag */ | /** | ||||||
|  |  * @template {keyof HTMLElementTagNameMap} TAG | ||||||
|  |  * @param {TAG} tag | ||||||
|  |  * @returns {ddeHTMLElementTagNameMap[TAG] extends HTMLElement ? ddeHTMLElementTagNameMap[TAG] : ddeHTMLElement} | ||||||
|  |  * */ | ||||||
| const createElement= tag=> chainableAppend(document.createElement(tag)); | const createElement= tag=> chainableAppend(document.createElement(tag)); | ||||||
| document.body.append( | document.body.append( | ||||||
| 	createElement("p").append( | 	createElement("p").append( | ||||||
| @@ -11,7 +11,7 @@ document.body.append( | |||||||
| ); | ); | ||||||
| 
 | 
 | ||||||
| function component({ className, textContent }){ | function component({ className, textContent }){ | ||||||
| 	return el("div", { className: [ "class1", className ] }).append( | 	return el("div", { className: [ "class1", className ].join(" ") }).append( | ||||||
| 		el("p", textContent) | 		el("p", textContent) | ||||||
| 	); | 	); | ||||||
| } | } | ||||||
| @@ -2,8 +2,8 @@ import { elNS, assign } from "deka-dom-el"; | |||||||
| const elSVG= elNS("http://www.w3.org/2000/svg"); | const elSVG= elNS("http://www.w3.org/2000/svg"); | ||||||
| const elMath= elNS("http://www.w3.org/1998/Math/MathML"); | const elMath= elNS("http://www.w3.org/1998/Math/MathML"); | ||||||
| document.body.append( | document.body.append( | ||||||
| 	elSVG("svg"), // see https://developer.mozilla.org/en-US/docs/Web/SVG and https://developer.mozilla.org/en-US/docs/Web/API/SVGElement
 | 	elSVG("svg"), // see https://developer.mozilla.org/en-US/docs/Web/SVG and https://developer.mozilla.org/en-US/docs/Web/API/SVGElement // editorconfig-checker-disable-line
 | ||||||
| 	elMath("math") // see https://developer.mozilla.org/en-US/docs/Web/MathML and https://developer.mozilla.org/en-US/docs/Web/MathML/Global_attributes
 | 	elMath("math") // see https://developer.mozilla.org/en-US/docs/Web/MathML and https://developer.mozilla.org/en-US/docs/Web/MathML/Global_attributes // editorconfig-checker-disable-line
 | ||||||
| ); | ); | ||||||
| 
 | 
 | ||||||
| console.log( | console.log( | ||||||
							
								
								
									
										19
									
								
								docs/components/examples/elements/native-dom-create.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								docs/components/examples/elements/native-dom-create.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,19 @@ | |||||||
|  | // Create element with properties | ||||||
|  | const button = document.createElement('button'); | ||||||
|  | button.textContent = "Click me"; | ||||||
|  | button.className = "primary"; | ||||||
|  | button.disabled = true; | ||||||
|  |  | ||||||
|  | // Or using Object.assign() | ||||||
|  | const button2 = Object.assign( | ||||||
|  | 	document.createElement('button'), | ||||||
|  | 	{ | ||||||
|  | 		textContent: "Click me", | ||||||
|  | 		className: "primary", | ||||||
|  | 		disabled: true | ||||||
|  | 	} | ||||||
|  | ); | ||||||
|  |  | ||||||
|  | // Add to DOM | ||||||
|  | document.body.append(button); | ||||||
|  | document.body.append(button2); | ||||||
							
								
								
									
										15
									
								
								docs/components/examples/elements/native-dom-tree.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								docs/components/examples/elements/native-dom-tree.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,15 @@ | |||||||
|  | // Verbose, needs temp variables | ||||||
|  | const div = document.createElement('div'); | ||||||
|  | const h1 = document.createElement('h1'); | ||||||
|  | h1.textContent = 'Title'; | ||||||
|  | div.append(h1); | ||||||
|  |  | ||||||
|  | const p = document.createElement('p'); | ||||||
|  | p.textContent = 'Paragraph'; | ||||||
|  | div.append(p); | ||||||
|  |  | ||||||
|  | // append doesn't return parent | ||||||
|  | // so chaining is not possible | ||||||
|  |  | ||||||
|  | // Add to DOM | ||||||
|  | document.body.append(div); | ||||||
							
								
								
									
										8
									
								
								docs/components/examples/events/append-event.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								docs/components/examples/events/append-event.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,8 @@ | |||||||
|  | import { el, on } from "deka-dom-el"; | ||||||
|  |  | ||||||
|  | // Third approach - append with on addon | ||||||
|  | el("button", { | ||||||
|  | 	textContent: "click me" | ||||||
|  | }).append( | ||||||
|  | 	on("click", (e) => console.log("Clicked!", e)) | ||||||
|  | ); | ||||||
							
								
								
									
										7
									
								
								docs/components/examples/events/attribute-event.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								docs/components/examples/events/attribute-event.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,7 @@ | |||||||
|  | import { el } from "deka-dom-el"; | ||||||
|  |  | ||||||
|  | // Using events with HTML attribute style | ||||||
|  | el("button", { | ||||||
|  | 	textContent: "click me", | ||||||
|  | 	"=onclick": "console.log(event)" | ||||||
|  | }); | ||||||
							
								
								
									
										8
									
								
								docs/components/examples/events/chain-event.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								docs/components/examples/events/chain-event.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,8 @@ | |||||||
|  | import { el, on } from "deka-dom-el"; | ||||||
|  |  | ||||||
|  | // Using events as addons - chainable approach | ||||||
|  | el("button", { | ||||||
|  | 	textContent: "click me", | ||||||
|  | }, | ||||||
|  | 	on("click", (e) => console.log("Clicked!", e)) | ||||||
|  | ); | ||||||
							
								
								
									
										19
									
								
								docs/components/examples/events/dispatch.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								docs/components/examples/events/dispatch.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,19 @@ | |||||||
|  | import { el, on, dispatchEvent, scope } from "deka-dom-el"; | ||||||
|  | document.body.append( | ||||||
|  | 	el(component), | ||||||
|  | ); | ||||||
|  |  | ||||||
|  | function component(){ | ||||||
|  | 	const { host }= scope; | ||||||
|  | 	const dispatchExample= dispatchEvent( | ||||||
|  | 		"example", | ||||||
|  | 		{ bubbles: true }, | ||||||
|  | 		host | ||||||
|  | 	); | ||||||
|  |  | ||||||
|  | 	return el("div").append( | ||||||
|  | 		el("p", "Dispatch events from outside of the component."), | ||||||
|  | 		el("button", { textContent: "Dispatch", type: "button" }, | ||||||
|  | 			on("click", dispatchExample)) | ||||||
|  | 	); | ||||||
|  | } | ||||||
							
								
								
									
										31
									
								
								docs/components/examples/events/live-cycle.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								docs/components/examples/events/live-cycle.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,31 @@ | |||||||
|  | import { el, on } from "deka-dom-el"; | ||||||
|  | function allLifecycleEvents(){ | ||||||
|  | 	return el("form", null, | ||||||
|  | 		el=> log({ type: "dde:created", detail: el }), | ||||||
|  | 		on.connected(log), | ||||||
|  | 		on.disconnected(log), | ||||||
|  | 	).append( | ||||||
|  | 		el("select", { id: "country" }, on.defer(select => { | ||||||
|  | 			// This runs when the select is ready with all its options | ||||||
|  | 			select.value = "cz"; // Pre-select Czechia | ||||||
|  | 			log({ type: "dde:on.defer", detail: select }); | ||||||
|  | 		})).append( | ||||||
|  | 			el("option", { value: "au", textContent: "Australia" }), | ||||||
|  | 			el("option", { value: "ca", textContent: "Canada" }), | ||||||
|  | 			el("option", { value: "cz", textContent: "Czechia" }), | ||||||
|  | 		), | ||||||
|  | 		el("p", "See lifecycle events in console."), | ||||||
|  | 	); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | document.body.append( | ||||||
|  | 	el(allLifecycleEvents), | ||||||
|  | 	el("button", "Remove Element", on("click", function(){ | ||||||
|  | 		this.previousSibling.remove(); | ||||||
|  | 	})) | ||||||
|  | ); | ||||||
|  |  | ||||||
|  | /** @param {Partial<CustomEvent>} event */ | ||||||
|  | function log({ type, detail }){ | ||||||
|  | 	console.log({ _this: this, type, detail }); | ||||||
|  | } | ||||||
							
								
								
									
										2
									
								
								docs/components/examples/events/native-event.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								docs/components/examples/events/native-event.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,2 @@ | |||||||
|  | // Standard DOM event listener approach | ||||||
|  | element.addEventListener('click', callback, options); | ||||||
							
								
								
									
										7
									
								
								docs/components/examples/events/property-event.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								docs/components/examples/events/property-event.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,7 @@ | |||||||
|  | import { el } from "deka-dom-el"; | ||||||
|  |  | ||||||
|  | // Using events with property assignment | ||||||
|  | el("button", { | ||||||
|  | 	textContent: "click me", | ||||||
|  | 	onclick: console.log | ||||||
|  | }); | ||||||
							
								
								
									
										13
									
								
								docs/components/examples/introducing/3ps-before.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								docs/components/examples/introducing/3ps-before.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | |||||||
|  | // pseudocode | ||||||
|  | // Mixed concerns make code hard to maintain | ||||||
|  | const button = document.querySelector('button'); | ||||||
|  | let count = 0; | ||||||
|  |  | ||||||
|  | button.addEventListener('click', () => { | ||||||
|  | 	count++; | ||||||
|  | 	document.querySelector('p').textContent = | ||||||
|  | 		'Clicked ' + count + ' times'; | ||||||
|  |  | ||||||
|  | 	if (count > 10) | ||||||
|  | 		button.disabled = true; | ||||||
|  | }); | ||||||
							
								
								
									
										14
									
								
								docs/components/examples/introducing/3ps.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								docs/components/examples/introducing/3ps.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,14 @@ | |||||||
|  | // pseudocode | ||||||
|  | // 1. Create state | ||||||
|  | const count = S(0); | ||||||
|  |  | ||||||
|  | // 2. React to state changes | ||||||
|  | S.on(count, value => { | ||||||
|  | 	updateUI(value); | ||||||
|  | 	if (value > 10) disableButton(); | ||||||
|  | }); | ||||||
|  |  | ||||||
|  | // 3. Update state on events | ||||||
|  | button.addEventListener('click', () => { | ||||||
|  | 	count.set(count.get() + 1); | ||||||
|  | }); | ||||||
							
								
								
									
										30
									
								
								docs/components/examples/introducing/helloWorld.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								docs/components/examples/introducing/helloWorld.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,30 @@ | |||||||
|  | import { el } from "deka-dom-el"; | ||||||
|  | import { S } from "deka-dom-el/signals"; | ||||||
|  |  | ||||||
|  | // A HelloWorld component using the 3PS pattern | ||||||
|  | function HelloWorld({ emoji = "🚀" }) { | ||||||
|  | 	// PART 1: Create reactive state | ||||||
|  | 	const clicks = S(0); | ||||||
|  |  | ||||||
|  | 	return el().append( | ||||||
|  | 		// PART 2: Bind state to UI elements | ||||||
|  | 		el("p", { | ||||||
|  | 			className: "greeting", | ||||||
|  | 			// This paragraph automatically updates when clicks changes | ||||||
|  | 			textContent: S(() => `Hello World ${emoji.repeat(clicks.get())}`) | ||||||
|  | 		}), | ||||||
|  |  | ||||||
|  | 		// PART 3: Update state in response to events | ||||||
|  | 		el("button", { | ||||||
|  | 			type: "button", | ||||||
|  | 			textContent: "Add emoji", | ||||||
|  | 			// When clicked, update the state | ||||||
|  | 			onclick: () => clicks.set(clicks.get() + 1) | ||||||
|  | 		}) | ||||||
|  | 	); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Use the component in your app | ||||||
|  | document.body.append( | ||||||
|  | 	el(HelloWorld, { emoji: "🎉" }) | ||||||
|  | ); | ||||||
							
								
								
									
										36
									
								
								docs/components/examples/introducing/motivation.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								docs/components/examples/introducing/motivation.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,36 @@ | |||||||
|  | import { el, on } from "deka-dom-el"; | ||||||
|  | import { S } from "deka-dom-el/signals"; | ||||||
|  | document.body.append( | ||||||
|  | 	el(HelloWorldComponent, { initial: "🚀" }) | ||||||
|  | ); | ||||||
|  | /** @typedef {"🎉" | "🚀"} Emoji */ | ||||||
|  | /** @param {{ initial: Emoji }} attrs */ | ||||||
|  | function HelloWorldComponent({ initial }){ | ||||||
|  | 	const clicks= S(0); | ||||||
|  | 	const emoji= S(initial); | ||||||
|  | 	/** @param {HTMLOptionElement} el */ | ||||||
|  | 	const isSelected= el=> (el.selected= el.value===initial); | ||||||
|  | 	// @ts-expect-error 2339: The <select> has only two options with {@link Emoji} | ||||||
|  | 	const onChange= on("change", event=> emoji(event.target.value)); | ||||||
|  |  | ||||||
|  | 	return el().append( | ||||||
|  | 		el("p", { | ||||||
|  | 			textContent: S(() => `Hello World ${emoji.get().repeat(clicks.get())}`), | ||||||
|  | 			className: "example", | ||||||
|  | 			ariaLive: "polite", //OR ariaset: { live: "polite" }, | ||||||
|  | 			dataset: { example: "Example" }, //OR dataExample: "Example", | ||||||
|  | 		}), | ||||||
|  | 		el("button", | ||||||
|  | 			{ textContent: "Fire", type: "button" }, | ||||||
|  | 			on("click", ()=> clicks.set(clicks.get() + 1)), | ||||||
|  | 			on("keyup", ()=> clicks.set(clicks.get() - 2)), | ||||||
|  | 		), | ||||||
|  | 		el("select", null, onChange).append( | ||||||
|  | 			el(OptionComponent, "🎉", isSelected),//OR { textContent: "🎉" } | ||||||
|  | 			el(OptionComponent, "🚀", isSelected),//OR { textContent: "🚀" } | ||||||
|  | 		) | ||||||
|  | 	); | ||||||
|  | } | ||||||
|  | function OptionComponent({ textContent }){ | ||||||
|  | 	return el("option", { value: textContent, textContent }) | ||||||
|  | } | ||||||
							
								
								
									
										37
									
								
								docs/components/examples/ireland-test/counter.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								docs/components/examples/ireland-test/counter.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,37 @@ | |||||||
|  | import { el } from "deka-dom-el"; | ||||||
|  | import { S } from "deka-dom-el/signals"; | ||||||
|  |  | ||||||
|  | const className = "client-side-counter"; | ||||||
|  | document.body.append( | ||||||
|  | 	el("style").append(` | ||||||
|  | .${className} { | ||||||
|  | 	border: 1px dashed #ccc; | ||||||
|  | 	padding: 1em; | ||||||
|  | 	margin: 1em; | ||||||
|  | } | ||||||
|  | `.trim()) | ||||||
|  | ); | ||||||
|  |  | ||||||
|  | export function CounterStandard() { | ||||||
|  | 	// Create reactive state with a signal | ||||||
|  | 	const count = S(0); | ||||||
|  |  | ||||||
|  | 	// Create UI components that react to state changes | ||||||
|  | 	return el("div", { className }).append( | ||||||
|  | 		el("h4", "Client-Side Counter"), | ||||||
|  | 		el("div", { | ||||||
|  | 			// The textContent updates automatically when count changes | ||||||
|  | 			textContent: S(() => `Count: ${count.get()}`), | ||||||
|  | 		}), | ||||||
|  | 		el("div", { className: "controls" }).append( | ||||||
|  | 			el("button", { | ||||||
|  | 				onclick: () => count.set(count.get() - 1), | ||||||
|  | 				textContent: "-", | ||||||
|  | 			}), | ||||||
|  | 			el("button", { | ||||||
|  | 				onclick: () => count.set(count.get() + 1), | ||||||
|  | 				textContent: "+", | ||||||
|  | 			}) | ||||||
|  | 		) | ||||||
|  | 	); | ||||||
|  | } | ||||||
							
								
								
									
										2
									
								
								docs/components/examples/optimization/intro.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								docs/components/examples/optimization/intro.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,2 @@ | |||||||
|  | // use NPM or for example https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-signals.js | ||||||
|  | import { memo } from "deka-dom-el"; | ||||||
							
								
								
									
										115
									
								
								docs/components/examples/optimization/memo.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										115
									
								
								docs/components/examples/optimization/memo.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,115 @@ | |||||||
|  | // Example of how memoization improves performance with list rendering | ||||||
|  | import { el, on, memo } from "deka-dom-el"; | ||||||
|  | import { S } from "deka-dom-el/signals"; | ||||||
|  |  | ||||||
|  | // A utility to log element creation | ||||||
|  | function logCreation(name) { | ||||||
|  | 	console.log(`Creating ${name} element`); | ||||||
|  | 	return name; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Create a signal with our items | ||||||
|  | const itemsSignal = S([ | ||||||
|  | 	{ id: 1, name: "Item 1" }, | ||||||
|  | 	{ id: 2, name: "Item 2" }, | ||||||
|  | 	{ id: 3, name: "Item 3" } | ||||||
|  | ], { | ||||||
|  | 		add() { | ||||||
|  | 				const { length }= this.value; | ||||||
|  | 				this.value.push({ | ||||||
|  | 						id: length + 1, | ||||||
|  | 						name: `Item ${length + 1}` | ||||||
|  | 				}); | ||||||
|  | 		}, | ||||||
|  | 		force(){}, | ||||||
|  | }); | ||||||
|  |  | ||||||
|  | // Without memoization - creates new elements on every render | ||||||
|  | function withoutMemo() { | ||||||
|  | 	return el("div").append( | ||||||
|  | 		el("h3", "Without Memoization (check console for element creation)"), | ||||||
|  | 		el("p", "Elements are recreated on every render"), | ||||||
|  | 		S.el(itemsSignal, items => | ||||||
|  | 			el("ul").append( | ||||||
|  | 				...items.map(item => | ||||||
|  | 					el("li").append( | ||||||
|  | 						el("span", logCreation(item.name)) | ||||||
|  | 					) | ||||||
|  | 				) | ||||||
|  | 			) | ||||||
|  | 		), | ||||||
|  | 	); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // With memoization - reuses elements when possible | ||||||
|  | function withMemo() { | ||||||
|  | 	return el("div").append( | ||||||
|  | 		el("h3", "With Memoization (check console for element creation)"), | ||||||
|  | 		el("p", "Elements are reused when the key (item.id) stays the same"), | ||||||
|  | 		S.el(itemsSignal, items => | ||||||
|  | 			el("ul").append( | ||||||
|  | 				...items.map(item => | ||||||
|  | 					// Use item.id as a stable key for memoization | ||||||
|  | 					memo(item.id, () => | ||||||
|  | 						el("li").append( | ||||||
|  | 							el("span", logCreation(item.name)) | ||||||
|  | 						) | ||||||
|  | 					) | ||||||
|  | 				) | ||||||
|  | 			) | ||||||
|  | 		), | ||||||
|  | 	); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Using memo.scope for a custom memoized function | ||||||
|  | const renderMemoList = memo.scope(function(items) { | ||||||
|  | 	return el("ul").append( | ||||||
|  | 		...items.map(item => | ||||||
|  | 			memo(item.id, () => | ||||||
|  | 				el("li").append( | ||||||
|  | 					el("span", logCreation(`Custom memo: ${item.name}`)) | ||||||
|  | 				) | ||||||
|  | 			) | ||||||
|  | 		) | ||||||
|  | 	); | ||||||
|  | }); | ||||||
|  |  | ||||||
|  | function withCustomMemo() { | ||||||
|  | 	return el("div").append( | ||||||
|  | 		el("h3", "With Custom Memo Function"), | ||||||
|  | 		el("p", "Using memo.scope to create a memoized rendering function"), | ||||||
|  | 		S.el(itemsSignal, items => | ||||||
|  | 			renderMemoList(items) | ||||||
|  | 		), | ||||||
|  | 		el("button", "Clear Cache", | ||||||
|  | 			on("click", () => { | ||||||
|  | 				renderMemoList.clear(); | ||||||
|  | 				S.action(itemsSignal, "force"); | ||||||
|  | 			} | ||||||
|  | 			) | ||||||
|  | 		) | ||||||
|  | 	); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Demo component showing the difference | ||||||
|  | export function MemoDemo() { | ||||||
|  | 	return el("div", { style: "padding: 1em; border: 1px solid #ccc;" }).append( | ||||||
|  | 		el("h2", "Memoization Demo"), | ||||||
|  | 		el("p", "See in the console when elements are created."), | ||||||
|  | 		el("p").append(` | ||||||
|  | 			Notice that without memoization, elements are recreated on every render. With memoization, | ||||||
|  | 			only new elements are created. | ||||||
|  | 		`), | ||||||
|  | 		el("button", "Add Item", | ||||||
|  | 			on("click", () => S.action(itemsSignal, "add")) | ||||||
|  | 		), | ||||||
|  |  | ||||||
|  | 		el("div", { style: "display: flex; gap: 2em; margin-top: 1em;" }).append( | ||||||
|  | 			withoutMemo(), | ||||||
|  | 			withMemo(), | ||||||
|  | 			withCustomMemo() | ||||||
|  | 		) | ||||||
|  | 	); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | document.body.append(el(MemoDemo)); | ||||||
							
								
								
									
										388
									
								
								docs/components/examples/reallife/todomvc.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										388
									
								
								docs/components/examples/reallife/todomvc.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,388 @@ | |||||||
|  | import { dispatchEvent, el, memo, on, scope } from "deka-dom-el"; | ||||||
|  | import { S } from "deka-dom-el/signals"; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Main TodoMVC application component | ||||||
|  |  * | ||||||
|  |  * Creates and manages the TodoMVC application with the following features: | ||||||
|  |  * - Todo items management (add, edit, delete) | ||||||
|  |  * - Filtering by status (all, active, completed) | ||||||
|  |  * - Client-side routing via URL hash | ||||||
|  |  * - Persistent storage with localStorage | ||||||
|  |  * | ||||||
|  |  * @returns {HTMLElement} The root TodoMVC application element | ||||||
|  |  */ | ||||||
|  | function Todos(){ | ||||||
|  | 	const { signal } = scope; | ||||||
|  | 	const pageS = routerSignal(S, signal); | ||||||
|  | 	const todosS = todosSignal(); | ||||||
|  | 	/** Derived signal that filters todos based on current route */ | ||||||
|  | 	const todosFilteredS = S(()=> { | ||||||
|  | 		const todos = todosS.get(); | ||||||
|  | 		const filter = pageS.get(); | ||||||
|  | 		if (filter === "all") return todos; | ||||||
|  | 		return todos.filter(todo => { | ||||||
|  | 			if (filter === "active") return !todo.completed; | ||||||
|  | 			if (filter === "completed") return todo.completed; | ||||||
|  | 		}); | ||||||
|  | 	}); | ||||||
|  | 	const todosRemainingS = S(()=> todosS.get().filter(todo => !todo.completed).length); | ||||||
|  |  | ||||||
|  | 	/** @type {ddeElementAddon<HTMLInputElement>} */ | ||||||
|  | 	const onToggleAll = on("change", event => { | ||||||
|  | 		const checked = /** @type {HTMLInputElement} */ (event.target).checked; | ||||||
|  | 		S.action(todosS, "completeAll", checked); | ||||||
|  | 	}); | ||||||
|  | 	const formNewTodo = "newTodo"; | ||||||
|  | 	/** @type {ddeElementAddon<HTMLFormElement>} */ | ||||||
|  | 	const onSubmitNewTodo = on("submit", event => { | ||||||
|  | 		event.preventDefault(); | ||||||
|  | 		const input = /** @type {HTMLInputElement} */( | ||||||
|  | 			/** @type {HTMLFormElement} */(event.target).elements.namedItem(formNewTodo) | ||||||
|  | 		); | ||||||
|  | 		const title = input.value.trim(); | ||||||
|  | 		if (!title) return; | ||||||
|  |  | ||||||
|  | 		S.action(todosS, "add", title); | ||||||
|  | 		input.value = ""; | ||||||
|  | 	}); | ||||||
|  | 	const onClearCompleted = on("click", () => S.action(todosS, "clearCompleted")); | ||||||
|  | 	const onDelete = on("todo:delete", ev => | ||||||
|  | 		S.action(todosS, "delete", /** @type {{ detail: Todo["id"] }} */(ev).detail)); | ||||||
|  | 	const onEdit = on("todo:edit", ev => | ||||||
|  | 		S.action(todosS, "edit", /** @type {{ detail: Partial<Todo> & { id: Todo["id"] } }} */(ev).detail)); | ||||||
|  |  | ||||||
|  | 	return el("section", { className: "todoapp" }).append( | ||||||
|  | 		el("header", { className: "header" }).append( | ||||||
|  | 			el("h1", "todos"), | ||||||
|  | 			el("form", null, onSubmitNewTodo).append( | ||||||
|  | 				el("input", { | ||||||
|  | 					className: "new-todo", | ||||||
|  | 					name: formNewTodo, | ||||||
|  | 					placeholder: "What needs to be done?", | ||||||
|  | 					autocomplete: "off", | ||||||
|  | 					autofocus: true | ||||||
|  | 				}) | ||||||
|  | 			) | ||||||
|  | 		), | ||||||
|  | 		S.el(todosS, todos => !todos.length | ||||||
|  | 			? el() | ||||||
|  | 			: el("main", { className: "main" }).append( | ||||||
|  | 				el("input", { | ||||||
|  | 					id: "toggle-all", | ||||||
|  | 					className: "toggle-all", | ||||||
|  | 					type: "checkbox" | ||||||
|  | 				}, onToggleAll), | ||||||
|  | 				el("label", { htmlFor: "toggle-all", title: "Mark all as complete" }), | ||||||
|  | 				el("ul", { className: "todo-list" }).append( | ||||||
|  | 					S.el(todosFilteredS, filteredTodos => filteredTodos.map(todo => | ||||||
|  | 						memo(todo.id, ()=> el(TodoItem, todo, onDelete, onEdit))) | ||||||
|  | 					) | ||||||
|  | 				) | ||||||
|  | 			) | ||||||
|  | 		), | ||||||
|  | 		S.el(todosS, todos => !todos.length | ||||||
|  | 			? el() | ||||||
|  | 			: el("footer", { className: "footer" }).append( | ||||||
|  | 				el("span", { className: "todo-count" }).append( | ||||||
|  | 					noOfLeft() | ||||||
|  | 				), | ||||||
|  | 				memo("filters", ()=> | ||||||
|  | 					el("ul", { className: "filters" }).append( | ||||||
|  | 						...[ "All", "Active", "Completed" ].map(textContent => | ||||||
|  | 							el("li").append( | ||||||
|  | 								el("a", { | ||||||
|  | 									textContent, | ||||||
|  | 									classList: { selected: S(()=> pageS.get() === textContent.toLowerCase()) }, | ||||||
|  | 									href: `#${textContent.toLowerCase()}` | ||||||
|  | 								}) | ||||||
|  | 							) | ||||||
|  | 						) | ||||||
|  | 					), | ||||||
|  | 				), | ||||||
|  | 				todos.length - todosRemainingS.get() === 0 | ||||||
|  | 					? el() | ||||||
|  | 					: memo("delete", () => | ||||||
|  | 						el("button", | ||||||
|  | 							{ textContent: "Clear completed", className: "clear-completed" }, | ||||||
|  | 							onClearCompleted) | ||||||
|  | 					) | ||||||
|  | 			) | ||||||
|  | 		) | ||||||
|  | 	); | ||||||
|  | 	function noOfLeft(){ | ||||||
|  | 		const length = todosRemainingS.get(); | ||||||
|  | 		return el("strong").append( | ||||||
|  | 			length + " ", | ||||||
|  | 			length === 1 ? "item left" : "items left" | ||||||
|  | 		) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Todo item data structure | ||||||
|  |  * @typedef {{ title: string, id: string, completed: boolean }} Todo | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Component for rendering an individual todo item | ||||||
|  |  * | ||||||
|  |  * Features: | ||||||
|  |  * - Display todo with completed state | ||||||
|  |  * - Toggle completion status | ||||||
|  |  * - Delete todo | ||||||
|  |  * - Edit todo with double-click | ||||||
|  |  * - Cancel edit with Escape key | ||||||
|  |  * | ||||||
|  |  * @param {Todo} todo - The todo item data | ||||||
|  |  * @fires {void} todo:delete - todo deletion event | ||||||
|  |  * @fires {Partial<Todo>} todo:edit - todo edits event | ||||||
|  |  */ | ||||||
|  | function TodoItem({ id, title, completed }) { | ||||||
|  | 	const { host }= scope; | ||||||
|  | 	const isEditing = S(false); | ||||||
|  | 	const isCompleted = S(completed); | ||||||
|  |  | ||||||
|  | 	/** @type {(id: string) => void} Dispatch function for deleting todo */ | ||||||
|  | 	const dispatchDelete= dispatchEvent("todo:delete", host); | ||||||
|  | 	/** @type {(data: {id: string, [key: string]: any}) => void} Dispatch function for editing todo */ | ||||||
|  | 	const dispatchEdit = dispatchEvent("todo:edit", host); | ||||||
|  |  | ||||||
|  | 	/** @type {ddeElementAddon<HTMLInputElement>} */ | ||||||
|  | 	const onToggleCompleted = on("change", (ev) => { | ||||||
|  | 		const completed= /** @type {HTMLInputElement} */(ev.target).checked; | ||||||
|  | 		isCompleted.set(completed); | ||||||
|  | 		dispatchEdit({ id, completed }); | ||||||
|  | 	}); | ||||||
|  | 	/** @type {ddeElementAddon<HTMLButtonElement>} */ | ||||||
|  | 	const onDelete = on("click", () => dispatchDelete(id)); | ||||||
|  | 	/** @type {ddeElementAddon<HTMLLabelElement>} */ | ||||||
|  | 	const onStartEdit = on("dblclick", () => isEditing.set(true)); | ||||||
|  | 	/** @type {ddeElementAddon<HTMLInputElement>} */ | ||||||
|  | 	const onBlurEdit = on("blur", event => { | ||||||
|  | 		const value = /** @type {HTMLInputElement} */(event.target).value.trim(); | ||||||
|  | 		if (value) { | ||||||
|  | 			dispatchEdit({ id, title: value }); | ||||||
|  | 		} else { | ||||||
|  | 			dispatchDelete(id); | ||||||
|  | 		} | ||||||
|  | 		isEditing.set(false); | ||||||
|  | 	}); | ||||||
|  | 	const formEdit = "edit"; | ||||||
|  | 	/** @type {ddeElementAddon<HTMLFormElement>} */ | ||||||
|  | 	const onSubmitEdit = on("submit", event => { | ||||||
|  | 		event.preventDefault(); | ||||||
|  | 		const input = /** @type {HTMLFormElement} */(event.target).elements.namedItem(formEdit); | ||||||
|  | 		const value = /** @type {HTMLInputElement} */(input).value.trim(); | ||||||
|  | 		if (value) { | ||||||
|  | 			dispatchEdit({ id, title: value }); | ||||||
|  | 		} else { | ||||||
|  | 			dispatchDelete(id); | ||||||
|  | 		} | ||||||
|  | 		isEditing.set(false); | ||||||
|  | 	}); | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * Event handler for keyboard events in edit mode | ||||||
|  | 	 * @type {ddeElementAddon<HTMLInputElement>} | ||||||
|  | 	 */ | ||||||
|  | 	const onKeyDown = on("keydown", event => { | ||||||
|  | 		if (event.key !== "Escape") return; | ||||||
|  | 		isEditing.set(false); | ||||||
|  | 	}); | ||||||
|  |  | ||||||
|  | 	return el("li", { classList: { completed: isCompleted, editing: isEditing } }).append( | ||||||
|  | 		el("div", { className: "view" }).append( | ||||||
|  | 			el("input", { | ||||||
|  | 				className: "toggle", | ||||||
|  | 				type: "checkbox", | ||||||
|  | 				checked: completed | ||||||
|  | 			}, onToggleCompleted), | ||||||
|  | 			el("label", { textContent: title }, onStartEdit), | ||||||
|  | 			el("button", { ariaLabel: "Delete todo", className: "destroy" }, onDelete) | ||||||
|  | 		), | ||||||
|  | 		S.el(isEditing, editing => !editing | ||||||
|  | 			? el() | ||||||
|  | 			: el("form", null, onSubmitEdit).append( | ||||||
|  | 				el("input", { | ||||||
|  | 					className: "edit", | ||||||
|  | 					name: formEdit, | ||||||
|  | 					value: title, | ||||||
|  | 				}, onBlurEdit, onKeyDown, addFocus) | ||||||
|  | 			) | ||||||
|  | 		) | ||||||
|  | 	); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Set up the document head | ||||||
|  | document.head.append( | ||||||
|  | 	el("title", "TodoMVC: dd<el>"), | ||||||
|  | 	el("meta", { name: "description", content: "A TodoMVC implementation using dd<el>." }), | ||||||
|  | 	el("link", { | ||||||
|  | 		rel: "stylesheet", | ||||||
|  | 		href: "https://cdn.jsdelivr.net/npm/todomvc-common@1.0.5/base.css" | ||||||
|  | 	}), | ||||||
|  | 	el("link", { | ||||||
|  | 		rel: "stylesheet", | ||||||
|  | 		href: "https://cdn.jsdelivr.net/npm/todomvc-app-css@2.4.2/index.css" | ||||||
|  | 	}) | ||||||
|  | ); | ||||||
|  |  | ||||||
|  | // Set up the document body | ||||||
|  | document.body.append( | ||||||
|  | 	el(Todos), | ||||||
|  | 	el("footer", { className: "info" }).append( | ||||||
|  | 		el("p", "Double-click to edit a todo"), | ||||||
|  | 		el("p").append( | ||||||
|  | 			"Created with ", | ||||||
|  | 			el("a", { textContent: "deka-dom-el", href: "https://github.com/jaandrle/deka-dom-el" }) | ||||||
|  | 		), | ||||||
|  | 		el("p").append( | ||||||
|  | 			"Part of ", | ||||||
|  | 			el("a", { textContent: "TodoMVC", href: "http://todomvc.com" }) | ||||||
|  | 		) | ||||||
|  | 	) | ||||||
|  | ); | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Utility function to set focus on an input element | ||||||
|  |  * Uses requestAnimationFrame to ensure the element is rendered | ||||||
|  |  * before trying to focus it | ||||||
|  |  * | ||||||
|  |  * @param {HTMLInputElement} editInput - The input element to focus | ||||||
|  |  * @returns {number} The requestAnimationFrame ID | ||||||
|  |  */ | ||||||
|  | function addFocus(editInput){ | ||||||
|  | 	return requestAnimationFrame(()=> { | ||||||
|  | 		editInput.focus(); | ||||||
|  | 		editInput.selectionStart = editInput.selectionEnd = editInput.value.length; | ||||||
|  | 	}); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Creates a signal for managing todos with persistence | ||||||
|  |  * | ||||||
|  |  * Features: | ||||||
|  |  * - Loads todos from localStorage on initialization | ||||||
|  |  * - Automatically saves todos to localStorage on changes | ||||||
|  |  * - Provides actions for adding, editing, deleting todos | ||||||
|  |  */ | ||||||
|  | function todosSignal(){ | ||||||
|  | 	const store_key = "dde-todos"; | ||||||
|  | 	// Try to load todos from localStorage | ||||||
|  | 	let savedTodos = []; | ||||||
|  | 	try { | ||||||
|  | 		const stored = localStorage.getItem(store_key); | ||||||
|  | 		if (stored) { | ||||||
|  | 			savedTodos = JSON.parse(stored); | ||||||
|  | 		} | ||||||
|  | 	} catch (_) {} | ||||||
|  |  | ||||||
|  | 	const out= S(/** @type {Todo[]} */(savedTodos || []), { | ||||||
|  | 		/** | ||||||
|  | 		 * Add a new todo | ||||||
|  | 		 * @param {string} value - The title of the new todo | ||||||
|  | 		 */ | ||||||
|  | 		add(value){ | ||||||
|  | 			this.value.push({ | ||||||
|  | 				completed: false, | ||||||
|  | 				title: value, | ||||||
|  | 				id: uuid(), | ||||||
|  | 			}); | ||||||
|  | 		}, | ||||||
|  | 		/** | ||||||
|  | 		 * Edit an existing todo | ||||||
|  | 		 * @param {{ id: string, [key: string]: any }} data - Object containing id and fields to update | ||||||
|  | 		 */ | ||||||
|  | 		edit({ id, ...update }){ | ||||||
|  | 			const index = this.value.findIndex(t => t.id === id); | ||||||
|  | 			if (index === -1) return this.stopPropagation(); | ||||||
|  | 			Object.assign(this.value[index], update); | ||||||
|  | 		}, | ||||||
|  | 		/** | ||||||
|  | 		 * Delete a todo by id | ||||||
|  | 		 * @param {string} id - The id of the todo to delete | ||||||
|  | 		 */ | ||||||
|  | 		delete(id){ | ||||||
|  | 			const index = this.value.findIndex(t => t.id === id); | ||||||
|  | 			if (index === -1) return this.stopPropagation(); | ||||||
|  | 			this.value.splice(index, 1); | ||||||
|  | 		}, | ||||||
|  | 		/** | ||||||
|  | 		 * Remove all completed todos | ||||||
|  | 		 */ | ||||||
|  | 		clearCompleted() { | ||||||
|  | 			this.value = this.value.filter(todo => !todo.completed); | ||||||
|  | 		}, | ||||||
|  | 		completeAll(state= true) { | ||||||
|  | 			this.value.forEach(todo => todo.completed = state); | ||||||
|  | 		}, | ||||||
|  | 		/** | ||||||
|  | 		 * Handle cleanup when signal is cleared | ||||||
|  | 		 */ | ||||||
|  | 		[S.symbols.onclear](){ | ||||||
|  | 		} | ||||||
|  | 	}); | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * Save todos to localStorage whenever the signal changes | ||||||
|  | 	 * @param {Todo[]} value - Current todos array | ||||||
|  | 	 */ | ||||||
|  | 	S.on(out, /** @param {Todo[]} value */ function saveTodos(value) { | ||||||
|  | 		try { | ||||||
|  | 			localStorage.setItem(store_key, JSON.stringify(value)); | ||||||
|  | 		} catch (e) { | ||||||
|  | 			console.error("Failed to save todos to localStorage", e); | ||||||
|  | 			// Optionally, provide user feedback | ||||||
|  | 		} | ||||||
|  | 	}); | ||||||
|  | 	return out; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Creates a signal for managing route state | ||||||
|  |  * | ||||||
|  |  * @param {typeof S} signal - The signal constructor from a library | ||||||
|  |  * @param {AbortSignal} abortSignal | ||||||
|  |  */ | ||||||
|  | function routerSignal(signal, abortSignal){ | ||||||
|  | 	const initial = location.hash.replace("#", "") || "all"; | ||||||
|  | 	const out = signal(initial, { | ||||||
|  | 		/** | ||||||
|  | 		 * Set the current route | ||||||
|  | 		 * @param {"all"|"active"|"completed"} hash - The route to set | ||||||
|  | 		 */ | ||||||
|  | 		set(hash){ | ||||||
|  | 			location.hash = hash; | ||||||
|  | 			//this.value = hash; | ||||||
|  | 		}, | ||||||
|  | 	}); | ||||||
|  |  | ||||||
|  | 	// Setup hash change listener | ||||||
|  | 	window.addEventListener("hashchange", () => { | ||||||
|  | 		const hash = location.hash.replace("#", "") || "all"; | ||||||
|  | 		//S.action(out, "set", /** @type {"all"|"active"|"completed"} */(hash)); | ||||||
|  | 		out.set(hash); | ||||||
|  | 	}, { signal: abortSignal }); | ||||||
|  |  | ||||||
|  | 	return out; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Generates a RFC4122 version 4 compliant UUID | ||||||
|  |  * Used to create unique identifiers for todo items | ||||||
|  |  * | ||||||
|  |  * @returns {string} A randomly generated UUID | ||||||
|  |  */ | ||||||
|  | function uuid() { | ||||||
|  | 	let uuid = ""; | ||||||
|  | 	for (let i = 0; i < 32; i++) { | ||||||
|  | 		let random = (Math.random() * 16) | 0; | ||||||
|  |  | ||||||
|  | 		if (i === 8 || i === 12 || i === 16 || i === 20) | ||||||
|  | 			uuid += "-"; | ||||||
|  |  | ||||||
|  | 		uuid += (i === 12 ? 4 : i === 16 ? (random & 3) | 8 : random).toString(16); | ||||||
|  | 	} | ||||||
|  | 	return uuid; | ||||||
|  | } | ||||||
| @@ -36,7 +36,7 @@ function elClass(_class, attributes, ...addons){ | |||||||
| 	}); | 	}); | ||||||
| 	element.prepend(el_mark); | 	element.prepend(el_mark); | ||||||
| 	if(is_fragment) element_host= el_mark; | 	if(is_fragment) element_host= el_mark; | ||||||
| 	 | 
 | ||||||
| 	chainableAppend(element); | 	chainableAppend(element); | ||||||
| 	addons.forEach(c=> c(element_host)); | 	addons.forEach(c=> c(element_host)); | ||||||
| 	scope.pop(); | 	scope.pop(); | ||||||
| @@ -1,4 +1,6 @@ | |||||||
| import { el, empty, on } from "deka-dom-el"; | import { el, on } from "deka-dom-el"; | ||||||
|  | /** @param {HTMLElement} el */ | ||||||
|  | const empty= el=> Array.from(el.children).forEach(c=> c.remove()); | ||||||
| document.body.append( | document.body.append( | ||||||
| 	el(component), | 	el(component), | ||||||
| 	el("button", { | 	el("button", { | ||||||
| @@ -12,7 +14,7 @@ function component(){ | |||||||
| 	const textContent= S("Click to change text."); | 	const textContent= S("Click to change text."); | ||||||
| 
 | 
 | ||||||
| 	const onclickChange= on("click", function redispatch(){ | 	const onclickChange= on("click", function redispatch(){ | ||||||
| 		textContent("Text changed! "+(new Date()).toString()) | 		textContent.set("Text changed! "+(new Date()).toString()) | ||||||
| 	}); | 	}); | ||||||
| 	return el("p", textContent, onclickChange); | 	return el("p", textContent, onclickChange); | ||||||
| } | } | ||||||
							
								
								
									
										26
									
								
								docs/components/examples/scopes/declarative.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								docs/components/examples/scopes/declarative.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | |||||||
|  | import { el } from "deka-dom-el"; | ||||||
|  | import { S } from "deka-dom-el/signals"; | ||||||
|  | function Counter() { | ||||||
|  | 	// Define state | ||||||
|  | 	const count = S(0); | ||||||
|  |  | ||||||
|  | 	// Define behavior | ||||||
|  | 	const increment = () => count.set(count.get() + 1); | ||||||
|  |  | ||||||
|  | 	// Define data flow | ||||||
|  | 	setTimeout(increment, 1000); | ||||||
|  | 	// or fetchAPI().then(increment); | ||||||
|  |  | ||||||
|  | 	// Declarative UI (how to render data/`count`) | ||||||
|  | 	// …automatically updates when changes | ||||||
|  | 	return el("div").append( | ||||||
|  | 		// declarative element(s) | ||||||
|  | 		el("p", S(() => "Count: " + count.get())), | ||||||
|  | 		el("button", { | ||||||
|  | 			onclick: increment, | ||||||
|  | 			textContent: "Increment", | ||||||
|  | 			// declarative attribute(s) | ||||||
|  | 			disabled: S(() => count.get() >= 10) | ||||||
|  | 		}) | ||||||
|  | 	); | ||||||
|  | } | ||||||
							
								
								
									
										25
									
								
								docs/components/examples/scopes/imperative.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								docs/components/examples/scopes/imperative.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,25 @@ | |||||||
|  | /* PSEUDO-CODE!!! */ | ||||||
|  | import { el, scope } from "deka-dom-el"; | ||||||
|  | function Counter() { | ||||||
|  | 	const { host } = scope; | ||||||
|  |  | ||||||
|  | 	let count = 0; | ||||||
|  | 	const counterText = el("p", "Count: 0"); | ||||||
|  |  | ||||||
|  | 	// Manually update DOM element | ||||||
|  | 	const increment = () => { | ||||||
|  | 		count++; | ||||||
|  | 		counterText.textContent = "Count: " + count; | ||||||
|  | 		host().querySelector("button").disabled = count >= 10; | ||||||
|  | 	}; | ||||||
|  | 	setTimeout(increment, 1000); | ||||||
|  | 	// or fetchAPI().then(increment); | ||||||
|  |  | ||||||
|  | 	return el("div").append( | ||||||
|  | 		counterText, | ||||||
|  | 		el("button", { | ||||||
|  | 			onclick: increment, | ||||||
|  | 			textContent: "Increment" | ||||||
|  | 		}) | ||||||
|  | 	); | ||||||
|  | } | ||||||
							
								
								
									
										38
									
								
								docs/components/examples/scopes/mixed.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								docs/components/examples/scopes/mixed.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,38 @@ | |||||||
|  | /* PSEUDO-CODE!!! */ | ||||||
|  | import { el, scope } from "deka-dom-el"; | ||||||
|  | import { S } from "deka-dom-el/signals"; | ||||||
|  | function Counter() { | ||||||
|  | 	const { host } = scope; | ||||||
|  |  | ||||||
|  | 	let count = S(0); | ||||||
|  | 	const counterText = el("p", "Count: 0"); | ||||||
|  | 	S.on(count, c=> counterText.textContent= "Count: " + c); | ||||||
|  |  | ||||||
|  | 	// Manually update DOM element | ||||||
|  | 	const increment = () => { | ||||||
|  | 		count.set(count.get() + 1); | ||||||
|  | 		// NEVER EVER | ||||||
|  | 		// count = S(count.get() + 1); | ||||||
|  | 		// THE HOST IS PROBABLY DIFFERENT THAN | ||||||
|  | 		// YOU EXPECT AND SIGNAL MAY BE | ||||||
|  | 		// UNEXPECTEDLY REMOVED!!! | ||||||
|  | 		S.on(count, (count)=> | ||||||
|  | 			host().querySelector("button").disabled = count >= 10 | ||||||
|  | 		); | ||||||
|  | 	}; | ||||||
|  | 	setTimeout(()=> { | ||||||
|  | 		// ok, BUT consider extract to separate function | ||||||
|  | 		// see section below for more info | ||||||
|  | 		const ok= S(0); | ||||||
|  | 		S.on(ok, console.log); | ||||||
|  | 		setInterval(()=> ok.set(ok.get() + 1), 100); | ||||||
|  | 	}, 100); | ||||||
|  |  | ||||||
|  | 	return el("div").append( | ||||||
|  | 		counterText, | ||||||
|  | 		el("button", { | ||||||
|  | 			onclick: increment, | ||||||
|  | 			textContent: "Increment" | ||||||
|  | 		}) | ||||||
|  | 	); | ||||||
|  | } | ||||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user