@public-ui/mcp 4.3.1-rc.4 → 4.4.0-rc.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +2 -2
- package/shared/sample-index.json +51 -35
- package/shared/template-index.json +79 -79
package/shared/sample-index.json
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"metadata": {
|
|
3
|
-
"generatedAt": "2026-09-
|
|
3
|
+
"generatedAt": "2026-09-07T13:52:19.220Z",
|
|
4
4
|
"buildMode": "ci",
|
|
5
5
|
"counts": {
|
|
6
|
-
"total":
|
|
7
|
-
"totalDocs":
|
|
6
|
+
"total": 334,
|
|
7
|
+
"totalDocs": 63,
|
|
8
8
|
"totalSpecs": 53,
|
|
9
|
-
"totalSamples":
|
|
9
|
+
"totalSamples": 198,
|
|
10
10
|
"totalScenarios": 20
|
|
11
11
|
},
|
|
12
12
|
"repo": {
|
|
13
|
-
"commit": "
|
|
13
|
+
"commit": "cec8305b216a7738d03e4812cfbfd473eb47251b",
|
|
14
14
|
"branch": "develop",
|
|
15
15
|
"repoUrl": "https://github.com/public-ui/kolibri"
|
|
16
16
|
}
|
|
@@ -341,7 +341,7 @@
|
|
|
341
341
|
"group": "docs",
|
|
342
342
|
"name": "CVE_OVERVIEW",
|
|
343
343
|
"path": "docs/CVE_OVERVIEW.md",
|
|
344
|
-
"code": "# CVE Overview\n\n> For more security information, see [SECURITY.md](./SECURITY.md)\n\n## 1. Production Dependencies\n\n### Summary\n\n| Severity | v4 | v3 | v2 | v1 |\n| -------- | --: | --: | --: | --: |\n| critical | 0 | 0 | 0 | 0 |\n| high | 2 | 17 | 2 | 16 |\n| moderate | 0 | 12 | 0 | 5 |\n| low | 0 | 2 | 0 | 0 |\n| info | 0 | 0 | 0 | 0 |\n| unknown | 0 | 0 | 0 | 0 |\n\n### Vulnerabilities\n\n| Package | Severity | CVE | Affected Versions | Description |\n| -------------------- | -------- | ------------------- | ----------------- | -------------------------------------------------------------------------------- |\n| @angular/common | high | CVE-2026-68945 | v3 | Angular: Cache-Key Ambiguity in HttpTransferCache Leading to Cross-Request Respo |\n| @angular/compiler | high | CVE-2026-69151 | v3 | Angular i18n: Cross-Site Scripting (XSS) via event-handler attributes |\n| @angular/core | high | CVE-2026-69151 | v3 | Angular i18n: Cross-Site Scripting (XSS) via event-handler attributes |\n| brace-expansion | high | CVE-2026-13149 | v1 | brace-expansion: DoS via exponential-time expansion of consecutive non-expanding |\n| brace-expansion | high | CVE-2026-14257 | v1 | brace-expansion: DoS via unbounded expansion length causing an out-of-memory pro |\n| brace-expansion | high | CVE-2026-69152 | v1 | brace-expansion: DoS via unbounded intermediate arrays, bypassing the CVE-2026-1 |\n| extract-zip | high | CVE-2026-56876 | v1 | extract-zip unvalidated symlink path traversal |\n| fast-uri | high | CVE-2026-18446 | v3, v1 | fast-uri vulnerable to host confusion via backslash authority introducer |\n| fast-uri | high | CVE-2026-16221 | v3 | fast-uri vulnerable to host confusion via literal backslash authority delimiter |\n| fast-uri | high | CVE-2026-13676 | v3 | fast-uri vulnerable to host confusion via failed IDN canonicalization |\n| find-my-way | high | CVE-2026-47219 | v3 | find-my-way: DDoS with HTTP2 |\n| image-size | high | CVE-2025-71330 | v4, v3, v2, v1 | image-size: ICNS parser allows denial of service through an infinite loop |\n| image-size | high | CVE-2025-71329 | v4, v3, v2, v1 | image-size: JXL and HEIF parsers allow denial of service through infinite loops |\n| immutable | high | CVE-2026-59879 | v3, v1 | Immutable.js `List` 32-bit trie overflow → unrecoverable DoS |\n| immutable | high | CVE-2026-59880 | v3, v1 | Immutable: Hash-collision algorithmic complexity denial of service in Immutable. |\n| ip-address | high | CVE-2026-69192 | v3 | ip-address: Address4 decodes leading-zero octets as decimal while resolvers deco |\n| js-yaml | high | GHSA-5p4m-2wfm-xmqj | v1 | JS-YAML: Quadratic CPU consumption in !!omap resolution (3.x and 4.x) — CVE-2026 |\n| linkify-it | high | CVE-2026-59887 | v3 | linkify-it: Quadratic-complexity DoS via the `mailto:` validator scan-loop on at |\n| lodash.pick | high | CVE-2020-8203 | v1 | Prototype Pollution in lodash |\n| minimatch | high | CVE-2026-27903 | v1 | minimatch has ReDoS: matchOne() combinatorial backtracking via multiple non-adja |\n| minimatch | high | CVE-2026-27904 | v1 | minimatch ReDoS: nested *() extglobs generate catastrophically backtracking regu |\n| nanoid | high | CVE-2026-67213 | v3, v1 | nanoid: custom generators can loop indefinitely when size is zero |\n| nanoid | high | CVE-2026-67214 | v3 | nanoid: non-secure generators can loop indefinitely with negative size |\n| postcss | high | CVE-2026-73646 | v3 | PostCSS: Path Traversal in Previous Source Map Auto-Loading (sourceMappingURL) l |\n| react-router | high | GHSA-qwww-vcr4-c8h2 | v3 | React Router: RSC Mode CSRF Bypass Allows Action Execution Before 400 Response |\n| serialize-javascript | high | GHSA-5c6j-r48x-rmvq | v1 | Serialize JavaScript is Vulnerable to RCE via RegExp.flags and Date.prototype.to |\n| @hono/node-server | moderate | GHSA-frvp-7c67-39w9 | v3 | Node.js Adapter for Hono: Path traversal in `serve-static` on Windows via encode |\n| brace-expansion | moderate | CVE-2026-45149 | v1 | brace-expansion: Large numeric range defeats documented `max` DoS protection |\n| dompurify | moderate | GHSA-55q2-fjhq-7xh7 | v1 | DOMPurify: IN_PLACE hook removal leaves a detached subtree executable, causing X |\n| hono | moderate | CVE-2026-59897 | v3 | Hono: API Gateway v1 adapter can drop a distinct repeated request header value d |\n| hono | moderate | CVE-2026-59896 | v3 | hono/jsx does not isolate context per request, leading to cross-request data dis |\n| hono | moderate | CVE-2026-59895 | v3 | Hono: Server-Side XSS via JSX Escaping Bypass in cx() Utility |\n| hono | moderate | CVE-2026-69207 | v3 | Hono: ReDoS in CORS middleware via Access-Control-Request-Headers |\n| hono | moderate | CVE-2026-71850 | v3 | Hono: `memo()` retains SSR output across requests, leading to cross-user data di |\n| hono | moderate | CVE-2026-71848 | v3 | Hono: Algorithmic Complexity DoS in Language Middleware |\n| ip-address | moderate | CVE-2026-69198 | v3 | ip-address: a CIDR suffix on the parsed address suppresses special-use classific |\n| ip-address | moderate | CVE-2026-54272 | v3 | ip-address: misclassification of IPv4-mapped/NAT64 IPv6 addresses can bypass SSR |\n| postcss | moderate | CVE-2026-69153 | v3 | PostCSS: incomplete fix of GHSA-6g55-p6wh-862q — attacker-controlled sourceMappi |\n| protobufjs | moderate | CVE-2026-59876 | v3 | protobufjs: Text Format string map parsing can mutate returned map object protot |\n| protobufjs | moderate | CVE-2026-59877 | v3 | protobufjs: Denial of Service via infinite loop in .proto option parsing |\n| qs | moderate | CVE-2026-8723 | v1 | qs has a remotely triggerable DoS: qs.stringify crashes with TypeError on null/u |\n| react-router-dom | moderate | CVE-2026-53668 | v1 | React Router: Open redirect leading to XSS |\n| serialize-javascript | moderate | CVE-2026-34043 | v1 | Serialize JavaScript has CPU Exhaustion Denial of Service via crafted array-like |\n| body-parser | low | CVE-2026-12590 | v3 | body-parser vulnerable to denial of service when invalid limit value silently di |\n| hono | low | CVE-2026-71849 | v3 | Hono: Proxy Helper does not remove response headers listed in the `Connection` h |\n\n## 2. All Dependencies\n\n### Summary\n\n| Severity | v4 | v3 | v2 | v1 |\n| -------- | --: | --: | --: | --: |\n| critical | 0 | 9 | 4 | 5 |\n| high | 19 | 106 | 82 | 59 |\n| moderate | 16 | 74 | 65 | 23 |\n| low | 2 | 13 | 13 | 3 |\n| info | 0 | 0 | 0 | 0 |\n| unknown | 0 | 0 | 0 | 0 |\n\n### Vulnerabilities\n\n| Package | Severity | CVE | Affected Versions | Description |\n| --------------------- | -------- | ------------------- | ----------------- | -------------------------------------------------------------------------------- |\n| basic-ftp | critical | CVE-2026-27699 | v3 | Basic FTP has Path Traversal Vulnerability in its downloadToDir() method |\n| fast-xml-parser | critical | CVE-2026-25896 | v3, v2 | fast-xml-parser has an entity encoding bypass via regex injection in DOCTYPE ent |\n| handlebars | critical | CVE-2026-33937 | v3, v1 | Handlebars.js has JavaScript Injection via AST Type Confusion |\n| locutus | critical | CVE-2026-25521 | v3, v1 | locutus is vulnerable to Prototype Pollution |\n| locutus | critical | CVE-2026-32304 | v3, v2, v1 | Locutus vulnerable to RCE via unsanitized input in create_function() |\n| seroval | critical | CVE-2026-59940 | v3, v2, v1 | seroval: `seroval.fromJSON()` Promise resolver type confusion invokes attacker-c |\n| shell-quote | critical | CVE-2026-9277 | v3 | shell-quote quote() does not escape newlines in object .op values |\n| tar | critical | CVE-2026-59873 | v3, v1 | node-tar: Decompression/parse DoS via unlimited input |\n| websocket-driver | critical | CVE-2026-54466 | v3, v2 | websocket-driver: Message corruption via abuse of protocol length headers |\n| @angular/common | high | CVE-2025-66035 | v1 | Angular is Vulnerable to XSRF Token Leakage via Protocol-Relative URLs in Angula |\n| @angular/common | high | CVE-2026-54268 | v4, v3, v2, v1 | @angular/common: Denial of Service (DoS) via OOM in Date Formatting (formatDate) |\n| @angular/common | high | CVE-2026-54266 | v4, v3, v2, v1 | @angular/common: Weak 32-Bit Cache Key Hashing in `HttpTransferCache` Leading to |\n| @angular/common | high | CVE-2026-50171 | v1 | @angular/common: Denial of Service (DoS) via OOM in Number Formatting (digitsInf |\n| @angular/common | high | CVE-2026-50170 | v1 | @angular/common: Information Leak via Default Caching of Credentialed Requests i |\n| @angular/common | high | CVE-2026-68945 | v4, v3, v2, v1 | Angular: Cache-Key Ambiguity in HttpTransferCache Leading to Cross-Request Respo |\n| @angular/compiler | high | CVE-2026-32635 | v1 | Angular vulnerable to XSS in i18n attribute bindings |\n| @angular/compiler | high | CVE-2026-22610 | v1 | Angular has XSS Vulnerability via Unsanitized SVG Script Attributes |\n| @angular/compiler | high | CVE-2025-66412 | v1 | Angular Stored XSS Vulnerability via SVG Animation, SVG URL and MathML Attribute |\n| @angular/compiler | high | CVE-2026-69151 | v4, v3, v2, v1 | Angular i18n: Cross-Site Scripting (XSS) via event-handler attributes |\n| @angular/core | high | CVE-2026-27970 | v1 | Angular i18n vulnerable to Cross-Site Scripting |\n| @angular/core | high | CVE-2026-32635 | v1 | Angular vulnerable to XSS in i18n attribute bindings |\n| @angular/core | high | CVE-2026-22610 | v1 | Angular has XSS Vulnerability via Unsanitized SVG Script Attributes |\n| @angular/core | high | CVE-2026-54267 | v4, v3, v2, v1 | Angular Client Hydration DOM Clobbering & Response-Cache Poisoning |\n| @angular/core | high | CVE-2026-69151 | v4, v3, v2, v1 | Angular i18n: Cross-Site Scripting (XSS) via event-handler attributes |\n| @hono/node-server | high | CVE-2026-29087 | v2 | @hono/node-server has authorization bypass for protected static paths via encode |\n| axios | high | CVE-2026-42043 | v3 | Axios: Incomplete Fix for CVE-2025-62718 — NO_PROXY Protection Bypassed via RFC |\n| axios | high | CVE-2026-42033 | v3 | Axios: Prototype Pollution Gadgets - Response Tampering, Data Exfiltration, and |\n| axios | high | CVE-2026-42035 | v3 | Axios: Header Injection via Prototype Pollution |\n| axios | high | CVE-2026-25639 | v3 | Axios is Vulnerable to Denial of Service via **proto** Key in mergeConfig |\n| axios | high | CVE-2026-42264 | v3 | Axios has prototype pollution read-side gadgets in HTTP adapter that allow crede |\n| axios | high | CVE-2026-44496 | v3 | Axios: Regular Expression Denial of Service (ReDoS) via Cookie Name Injection |\n| axios | high | CVE-2026-44488 | v3 | Allocation of Resources Without Limits or Throttling in Axios |\n| axios | high | CVE-2026-44487 | v3 | Axios: Proxy-Authorization Credential Leak to Origin Server Across HTTP-to-HTTPS |\n| axios | high | CVE-2026-44486 | v3 | Axios: Proxy-Authorization header leaks to redirect target when proxy is re-eval |\n| axios | high | CVE-2026-44495 | v3 | axios Vulnerable to Credential Theft and Response Hijacking via Prototype Pollut |\n| axios | high | CVE-2026-44494 | v3 | axios Vulnerable to Full Man-in-the-Middle via Prototype Pollution Gadget in `co |\n| basic-ftp | high | GHSA-6v7q-wjvx-w8wg | v3 | basic-ftp: Incomplete CRLF Injection Protection Allows Arbitrary FTP Command Exe |\n| basic-ftp | high | CVE-2026-41324 | v3 | basic-ftp vulnerable to denial of service via unbounded memory consumption in Cl |\n| basic-ftp | high | CVE-2026-44240 | v3 | basic-ftp allows a malicious FTP server to cause client-side denial of service v |\n| brace-expansion | high | CVE-2026-13149 | v3, v2, v1 | brace-expansion: DoS via exponential-time expansion of consecutive non-expanding |\n| brace-expansion | high | CVE-2026-14257 | v3, v2, v1 | brace-expansion: DoS via unbounded expansion length causing an out-of-memory pro |\n| brace-expansion | high | CVE-2026-69152 | v3, v2, v1 | brace-expansion: DoS via unbounded intermediate arrays, bypassing the CVE-2026-1 |\n| braces | high | CVE-2024-4068 | v3, v2, v1 | Uncontrolled resource consumption in braces |\n| deepmerge-ts | high | CVE-2026-40345 | v4, v3, v2 | DeepmergeTS has stack exhaustion when merging recursive object graphs |\n| engine.io | high | CVE-2026-59725 | v3, v2 | Socket.IO: Engine.IO Polling Transport Connection Exhaustion |\n| express-rate-limit | high | CVE-2026-30827 | v2 | express-rate-limit: IPv4-mapped IPv6 addresses bypass per-client rate limiting o |\n| extract-zip | high | CVE-2026-56876 | v4, v3, v2, v1 | extract-zip unvalidated symlink path traversal |\n| fast-uri | high | CVE-2026-18446 | v3, v2, v1 | fast-uri vulnerable to host confusion via backslash authority introducer |\n| fast-uri | high | CVE-2026-16221 | v3, v2 | fast-uri vulnerable to host confusion via literal backslash authority delimiter |\n| fast-uri | high | CVE-2026-6321 | v2 | fast-uri vulnerable to path traversal via percent-encoded dot segments |\n| fast-uri | high | CVE-2026-13676 | v3, v2 | fast-uri vulnerable to host confusion via failed IDN canonicalization |\n| fast-uri | high | CVE-2026-6322 | v2 | fast-uri vulnerable to host confusion via percent-encoded authority delimiters |\n| fast-xml-parser | high | CVE-2026-25128 | v3, v2 | fast-xml-parser has RangeError DoS Numeric Entities Bug |\n| fast-xml-parser | high | CVE-2026-26278 | v3, v2 | fast-xml-parser affected by DoS through entity expansion in DOCTYPE (no expansio |\n| fast-xml-parser | high | CVE-2026-33036 | v3, v2 | fast-xml-parser affected by numeric entity expansion bypassing all entity expans |\n| find-my-way | high | CVE-2026-47219 | v3 | find-my-way: DDoS with HTTP2 |\n| flatted | high | CVE-2026-32141 | v3, v2 | flatted vulnerable to unbounded recursion DoS in parse() revive phase |\n| flatted | high | CVE-2026-33228 | v3, v2 | Prototype Pollution via parse() in NodeJS flatted |\n| form-data | high | CVE-2026-12143 | v3, v2, v1 | form-data: CRLF injection in form-data via unescaped multipart field names and f |\n| handlebars | high | CVE-2026-33938 | v3, v1 | Handlebars.js has JavaScript Injection via AST Type Confusion by tampering @part |\n| handlebars | high | CVE-2026-33940 | v3, v1 | Handlebars.js has JavaScript Injection via AST Type Confusion when passing an ob |\n| handlebars | high | CVE-2026-33939 | v3, v1 | Handlebars.js has Denial of Service via Malformed Decorator Syntax in Template C |\n| handlebars | high | CVE-2026-33941 | v3, v1 | Handlebars.js has JavaScript Injection in CLI Precompiler via Unescaped Names an |\n| hono | high | CVE-2026-29045 | v2 | Hono vulnerable to arbitrary file access via serveStatic vulnerability |\n| hono | high | CVE-2026-54290 | v2 | hono: CORS Middleware reflects any Origin with credentials when `origin` default |\n| http-proxy-middleware | high | CVE-2026-55603 | v3 | http-proxy-middleware: multipart/form-data field injection via unescaped CRLF in |\n| image-size | high | CVE-2025-71330 | v4, v3, v2, v1 | image-size: ICNS parser allows denial of service through an infinite loop |\n| image-size | high | CVE-2025-71329 | v4, v3, v2, v1 | image-size: JXL and HEIF parsers allow denial of service through infinite loops |\n| immutable | high | CVE-2026-59879 | v3, v2, v1 | Immutable.js `List` 32-bit trie overflow → unrecoverable DoS |\n| immutable | high | CVE-2026-59880 | v3, v2, v1 | Immutable: Hash-collision algorithmic complexity denial of service in Immutable. |\n| immutable | high | CVE-2026-29063 | v2 | Immutable is vulnerable to Prototype Pollution |\n| ip-address | high | CVE-2026-69192 | v3, v2 | ip-address: Address4 decodes leading-zero octets as decimal while resolvers deco |\n| js-yaml | high | GHSA-5p4m-2wfm-xmqj | v3, v2, v1 | JS-YAML: Quadratic CPU consumption in !!omap resolution (3.x and 4.x) — CVE-2026 |\n| js-yaml | high | CVE-2026-59869 | v3, v2 | js-yaml: YAML merge-key chains can force quadratic CPU consumption |\n| linkify-it | high | CVE-2026-59887 | v3 | linkify-it: Quadratic-complexity DoS via the `mailto:` validator scan-loop on at |\n| locutus | high | CVE-2026-29091 | v3, v2, v1 | locutus call_user_func_array vulnerable to Remote Code Execution (RCE) due to Co |\n| lodash | high | CVE-2026-4800 | v3 | lodash vulnerable to Code Injection via `_.template` imports key names |\n| lodash.pick | high | CVE-2020-8203 | v2, v1 | Prototype Pollution in lodash |\n| minimatch | high | CVE-2026-27903 | v3, v2, v1 | minimatch has ReDoS: matchOne() combinatorial backtracking via multiple non-adja |\n| minimatch | high | CVE-2026-27904 | v3, v2, v1 | minimatch ReDoS: nested *() extglobs generate catastrophically backtracking regu |\n| minimatch | high | CVE-2026-26996 | v3, v2 | minimatch has a ReDoS via repeated wildcards with non-matching literal in patter |\n| nanoid | high | CVE-2026-67213 | v3, v1 | nanoid: custom generators can loop indefinitely when size is zero |\n| nanoid | high | CVE-2026-67214 | v3 | nanoid: non-secure generators can loop indefinitely with negative size |\n| node-forge | high | CVE-2026-33896 | v2 | Forge has a basicConstraints bypass in its certificate chain verification (RFC 5 |\n| node-forge | high | CVE-2026-33895 | v2 | Forge has signature forgery in Ed25519 due to missing S > L check |\n| node-forge | high | CVE-2026-33891 | v2 | Forge has Denial of Service via Infinite Loop in BigInteger.modInverse() with Ze |\n| node-forge | high | CVE-2026-33894 | v2 | Forge has signature forgery in RSA-PKCS due to ASN.1 extra field |\n| nx | high | CVE-2026-71476 | v3, v1 | Nx: Zip-Slip in the self-hosted remote cache |\n| pacote | high | CVE-2026-9496 | v3, v2, v1 | pacote is vulnerable to Denial of Service (DoS) via the addGitSha function |\n| path-to-regexp | high | CVE-2026-4867 | v3, v2 | path-to-regexp vulnerable to Regular Expression Denial of Service via multiple r |\n| path-to-regexp | high | CVE-2026-4926 | v2 | path-to-regexp vulnerable to Denial of Service via sequential optional groups |\n| piscina | high | CVE-2026-55388 | v3 | piscina: Prototype Pollution Gadget → RCE via inherited options.filename |\n| postcss | high | CVE-2026-45623 | v4, v3, v2 | PostCSS: Arbitrary file read and information disclosure via attacker-controlled |\n| postcss | high | CVE-2026-73646 | v4, v3, v2 | PostCSS: Path Traversal in Previous Source Map Auto-Loading (sourceMappingURL) l |\n| react-router | high | GHSA-qwww-vcr4-c8h2 | v3 | React Router: RSC Mode CSRF Bypass Allows Action Execution Before 400 Response |\n| rollup | high | CVE-2026-27606 | v1 | Rollup 4 has Arbitrary File Write via Path Traversal |\n| semver | high | CVE-2022-25883 | v2 | semver vulnerable to Regular Expression Denial of Service |\n| serialize-javascript | high | GHSA-5c6j-r48x-rmvq | v4, v3, v2, v1 | Serialize JavaScript is Vulnerable to RCE via RegExp.flags and Date.prototype.to |\n| shell-quote | high | CVE-2026-13311 | v3 | shell-quote: Quadratic-complexity Denial of Service in `parse()` (CWE-407) |\n| sigstore | high | CVE-2026-48815 | v3, v2, v1 | sigstore's `certificateOIDs` verification constraints are silently dropped and n |\n| socket.io-parser | high | CVE-2026-33151 | v3, v2 | socket.io allows an unbounded number of binary attachments |\n| socket.io-parser | high | CVE-2026-69185 | v3, v2 | Socket.IO: Zero-attachment Memory Exhaustion |\n| svgo | high | CVE-2026-29074 | v3, v2, v1 | SVGO DoS through entity expansion in DOCTYPE (Billion Laughs) |\n| svgo | high | CVE-2026-73650 | v3, v2, v1 | SVGO removeScripts plugin leaves some executable scripts intact |\n| tar | high | CVE-2026-24842 | v1 | node-tar Vulnerable to Arbitrary File Creation/Overwrite via Hardlink Path Trave |\n| tar | high | CVE-2026-23745 | v1 | node-tar is Vulnerable to Arbitrary File Overwrite and Symlink Poisoning via Ins |\n| tar | high | CVE-2026-26960 | v1 | Arbitrary File Read/Write via Hardlink Target Escape Through Symlink Chain in no |\n| tar | high | CVE-2026-29786 | v1 | tar has Hardlink Path Traversal via Drive-Relative Linkpath |\n| tar | high | CVE-2026-31802 | v1 | node-tar Symlink Path Traversal via Drive-Relative Linkpath |\n| tar | high | CVE-2026-23950 | v1 | Race Condition in node-tar Path Reservations via Unicode Ligature Collisions on |\n| tar | high | CVE-2026-59874 | v3, v1 | node-tar: Negative tar entry size causes infinite loop in archive replace |\n| tar | high | CVE-2026-73566 | v3, v2, v1 | node-tar: Uncontrolled recursion in mapHas/filesFilter allows uncatchable stack- |\n| tmp | high | CVE-2026-44705 | v3, v2 | tmp has Path Traversal via unsanitized prefix/postfix that enables directory esc |\n| undici | high | CVE-2026-1528 | v3 | Undici: Malicious WebSocket 64-bit length overflows parser and crashes the clien |\n| undici | high | CVE-2026-1526 | v3 | Undici has Unbounded Memory Consumption in WebSocket permessage-deflate Decompre |\n| undici | high | CVE-2026-2229 | v3 | Undici has Unhandled Exception in WebSocket Client Due to Invalid server_max_win |\n| undici | high | CVE-2026-9697 | v3 | undici vulnerable to TLS certificate validation bypass via dropped requestTls in |\n| undici | high | CVE-2026-12151 | v3 | undici WebSocket client vulnerable to denial of service via fragment count bypas |\n| undici | high | CVE-2026-6734 | v3 | undici vulnerable to cross-origin request routing via SOCKS5 proxy pool reuse |\n| undici | high | CVE-2026-13697 | v3 | undici vulnerable to cross-user information disclosure and parse-time crash via |\n| vite | high | CVE-2026-39364 | v1 | Vite: `server.fs.deny` bypassed with queries |\n| vite | high | CVE-2026-39363 | v1 | Vite Vulnerable to Arbitrary File Read via Vite Dev Server WebSocket |\n| vite | high | CVE-2026-53571 | v3, v1 | vite: `server.fs.deny` bypass on Windows alternate paths |\n| ws | high | CVE-2026-48779 | v3, v2, v1 | ws: Memory exhaustion DoS from tiny fragments and data chunks |\n| @angular/compiler | moderate | CVE-2026-54265 | v4, v3, v2, v1 | @angular/compiler: Two-Way Property Binding Sanitization Bypass (XSS) |\n| @angular/compiler | moderate | CVE-2026-50557 | v4, v1 | Angular: Template and Attribute Namespace Sanitization Bypass (XSS) |\n| @angular/core | moderate | CVE-2026-50557 | v4, v1 | Angular: Template and Attribute Namespace Sanitization Bypass (XSS) |\n| @angular/core | moderate | CVE-2026-52725 | v4, v1 | @angular/core: Angular Template and Dynamic Component Namespace Bypass leading t |\n| @hono/node-server | moderate | CVE-2026-39406 | v2 | @hono/node-server: Middleware bypass via repeated slashes in serveStatic |\n| @hono/node-server | moderate | GHSA-frvp-7c67-39w9 | v3, v2 | Node.js Adapter for Hono: Path traversal in `serve-static` on Windows via encode |\n| @opentelemetry/core | moderate | CVE-2026-54285 | v1 | OpenTelemetry Core: Unbounded memory allocation in W3C Baggage propagation |\n| @sigstore/core | moderate | CVE-2026-48758 | v3, v2, v1 | @sigstore/core has DSSE payloadType type-binding failure |\n| ajv | moderate | CVE-2025-69873 | v3, v2 | ajv has ReDoS when using `$data` option |\n| axios | moderate | CVE-2025-62718 | v3 | Axios has a NO_PROXY Hostname Normalization Bypass that Leads to SSRF |\n| axios | moderate | CVE-2026-42041 | v3 | Axios: Authentication Bypass via Prototype Pollution Gadget in `validateStatus` |\n| axios | moderate | CVE-2026-42044 | v3 | Axios: Invisible JSON Response Tampering via Prototype Pollution Gadget in `pars |\n| axios | moderate | CVE-2026-42037 | v3 | Axios: CRLF Injection in multipart/form-data body via unsanitized blob.type in f |\n| axios | moderate | CVE-2026-42038 | v3 | Axios: no_proxy bypass via IP alias allows SSRF |\n| axios | moderate | CVE-2026-42034 | v3 | Axios' HTTP adapter-streamed uploads bypass maxBodyLength when maxRedirects: 0 |\n| axios | moderate | CVE-2026-42036 | v3 | Axios: HTTP adapter streamed responses bypass maxContentLength |\n| axios | moderate | CVE-2026-42042 | v3 | Axios: XSRF Token Cross-Origin Leakage via Prototype Pollution Gadget in `withXS |\n| axios | moderate | CVE-2026-40175 | v3 | Axios has Unrestricted Cloud Metadata Exfiltration via Header Injection Chain |\n| axios | moderate | CVE-2026-42039 | v3 | Axios: unbounded recursion in toFormData causes DoS via deeply nested request da |\n| axios | moderate | CVE-2026-44490 | v3 | axios has DoS & Header Injection via Prototype Pollution Read-Side Gadgets in ax |\n| axios | moderate | GHSA-42h9-826w-cgv3 | v3 | Axios: Excessive recursion in formDataToJSON can cause denial of service |\n| axios | moderate | GHSA-pmv8-rq9r-6j72 | v3 | Axios: Deep formToJSON Key Recursion Can Cause Denial of Service |\n| axios | moderate | GHSA-jqh4-m9w3-8hp9 | v3 | Axios: Fetch adapter `ReadableStream` uploads bypass `maxBodyLength` |\n| axios | moderate | GHSA-mmx7-hfxf-jppx | v3 | Axios: Prototype pollution gadgets can alter axios request construction |\n| axios | moderate | GHSA-7q8q-rj6j-mhjq | v3 | Axios: Nested axios option objects can consume polluted prototype values |\n| brace-expansion | moderate | CVE-2026-45149 | v3, v2, v1 | brace-expansion: Large numeric range defeats documented `max` DoS protection |\n| brace-expansion | moderate | CVE-2026-33750 | v3, v2 | brace-expansion: Zero-step sequence causes process hang and memory exhaustion |\n| dompurify | moderate | GHSA-55q2-fjhq-7xh7 | v1 | DOMPurify: IN_PLACE hook removal leaves a detached subtree executable, causing X |\n| ejs | moderate | CVE-2024-33883 | v2 | ejs lacks certain pollution protection |\n| esbuild | moderate | GHSA-67mh-4wv8-2f99 | v2 | esbuild enables any website to send any requests to the development server and r |\n| fast-xml-parser | moderate | CVE-2026-33349 | v3, v2 | Entity Expansion Limits Bypassed When Set to Zero Due to JavaScript Falsy Evalua |\n| fast-xml-parser | moderate | CVE-2026-41650 | v3, v2 | fast-xml-parser XMLBuilder: XML Comment and CDATA Injection via Unescaped Delimi |\n| file-type | moderate | CVE-2026-31808 | v4 | file-type affected by infinite loop in ASF parser on malformed input with zero-s |\n| handlebars | moderate | CVE-2026-33916 | v3, v1 | Handlebars.js has Prototype Pollution Leading to XSS through Partial Template In |\n| handlebars | moderate | GHSA-7rx3-28cr-v5wh | v3, v1 | Handlebars.js has a Prototype Method Access Control Gap via Missing __lookupSett |\n| hono | moderate | CVE-2026-29086 | v2 | Hono Vulnerable to Cookie Attribute Injection via Unsanitized domain and path in |\n| hono | moderate | CVE-2026-29085 | v2 | Hono Vulnerable to SSE Control Field Injection via CR/LF in writeSSE() |\n| hono | moderate | GHSA-v8w9-8mx6-g223 | v2 | Hono vulnerable to Prototype Pollution possible through **proto** key allowed in |\n| hono | moderate | GHSA-26pp-8wgv-hjvm | v2 | Hono missing validation of cookie name on write path in setCookie() |\n| hono | moderate | CVE-2026-39410 | v2 | Hono: Non-breaking space prefix bypass in cookie name handling in getCookie() |\n| hono | moderate | CVE-2026-39408 | v2 | Hono: Path traversal in toSSG() allows writing files outside the output director |\n| hono | moderate | CVE-2026-39407 | v2 | Hono: Middleware bypass via repeated slashes in serveStatic |\n| hono | moderate | CVE-2026-39409 | v2 | Hono has incorrect IP matching in ipRestriction() for IPv4-mapped IPv6 addresses |\n| hono | moderate | CVE-2026-44458 | v2 | Hono has CSS Declaration Injection via Style Object Values in JSX SSR |\n| hono | moderate | CVE-2026-44457 | v2 | Hono's Cache Middleware ignores Vary: Authorization / Vary: Cookie leading to cr |\n| hono | moderate | CVE-2026-44456 | v2 | Hono: bodyLimit() can be bypassed for chunked / unknown-length requests |\n| hono | moderate | CVE-2026-44455 | v2 | hono/jsx has Unvalidated JSX Tag Names that May Allow HTML Injection |\n| hono | moderate | CVE-2026-47674 | v2 | Hono: IP Restriction bypasses static deny rules for non-canonical IPv6 |\n| hono | moderate | CVE-2026-47675 | v2 | Hono: Cookie helper does not sanitize sameSite and priority, allowing Set-Cookie |\n| hono | moderate | CVE-2026-47673 | v2 | Hono: JWT middleware accepts any Authorization scheme, not only Bearer |\n| hono | moderate | CVE-2026-47676 | v2 | Hono: app.mount() strips mount prefix using undecoded path, causing incorrect ro |\n| hono | moderate | CVE-2026-56761 | v2 | hono Improperly Handles JSX Attribute Names Allows HTML Injection in hono/jsx SS |\n| hono | moderate | CVE-2026-54288 | v2 | hono: Body Limit Middleware can be bypassed on AWS Lambda by understating `Conte |\n| hono | moderate | CVE-2026-54289 | v2 | hono: Lambda@Edge adapter keeps only the last value of a repeated request header |\n| hono | moderate | CVE-2026-54286 | v2 | hono: Path traversal in `serve-static` on Windows via encoded backslash (`%5C`) |\n| hono | moderate | CVE-2026-54287 | v2 | hono: AWS Lambda adapter merges multiple `Set-Cookie` headers into one value, dr |\n| hono | moderate | CVE-2026-59897 | v3, v2 | Hono: API Gateway v1 adapter can drop a distinct repeated request header value d |\n| hono | moderate | CVE-2026-59895 | v3, v2 | Hono: Server-Side XSS via JSX Escaping Bypass in cx() Utility |\n| hono | moderate | CVE-2026-69207 | v3, v2 | Hono: ReDoS in CORS middleware via Access-Control-Request-Headers |\n| hono | moderate | CVE-2026-71850 | v3, v2 | Hono: `memo()` retains SSR output across requests, leading to cross-user data di |\n| hono | moderate | CVE-2026-59896 | v3 | hono/jsx does not isolate context per request, leading to cross-request data dis |\n| hono | moderate | CVE-2026-71848 | v3 | Hono: Algorithmic Complexity DoS in Language Middleware |\n| http-proxy-middleware | moderate | CVE-2026-55602 | v3, v2 | http-proxy-middleware `router` host+path substring matching allows Host-header-d |\n| ip-address | moderate | CVE-2026-42338 | v2 | ip-address has XSS in Address6 HTML-emitting methods |\n| ip-address | moderate | CVE-2026-69198 | v3 | ip-address: a CIDR suffix on the parsed address suppresses special-use classific |\n| ip-address | moderate | CVE-2026-54272 | v3 | ip-address: misclassification of IPv4-mapped/NAT64 IPv6 addresses can bypass SSR |\n| js-yaml | moderate | CVE-2025-64718 | v2 | js-yaml has prototype pollution in merge (<<) |\n| js-yaml | moderate | CVE-2026-53550 | v3, v2 | JS-YAML: Quadratic-complexity DoS in merge key handling via repeated aliases |\n| launch-editor | moderate | CVE-2026-53632 | v3, v2 | launch-editor: NTLMv2 hash disclosure via UNC path handling on Windows |\n| locutus | moderate | CVE-2026-33993 | v3, v2, v1 | Locutus has Prototype Pollution via **proto** Key Injection in unserialize() |\n| locutus | moderate | CVE-2026-33994 | v2 | Locutus Prototype Pollution due to incomplete fix for CVE-2026-25521 |\n| lodash | moderate | CVE-2026-2950 | v3 | lodash vulnerable to Prototype Pollution via array path bypass in `_.unset` and |\n| micromatch | moderate | CVE-2024-4067 | v3, v2, v1 | Regular Expression Denial of Service (ReDoS) in micromatch |\n| nx | moderate | CVE-2026-54753 | v3, v1 | `nx graph` dev server permissive CORS policy |\n| path-to-regexp | moderate | CVE-2026-4923 | v2 | path-to-regexp vulnerable to Regular Expression Denial of Service via multiple w |\n| postcss | moderate | CVE-2026-41305 | v4, v3, v2 | PostCSS has XSS via Unescaped </style> in its CSS Stringify Output |\n| postcss | moderate | CVE-2026-69153 | v4, v3, v2 | PostCSS: incomplete fix of GHSA-6g55-p6wh-862q — attacker-controlled sourceMappi |\n| protobufjs | moderate | CVE-2026-59876 | v3 | protobufjs: Text Format string map parsing can mutate returned map object protot |\n| protobufjs | moderate | CVE-2026-59877 | v3 | protobufjs: Denial of Service via infinite loop in .proto option parsing |\n| qs | moderate | CVE-2026-8723 | v3, v2, v1 | qs has a remotely triggerable DoS: qs.stringify crashes with TypeError on null/u |\n| qs | moderate | CVE-2025-15284 | v2 | qs's arrayLimit bypass in its bracket notation allows DoS via memory exhaustion |\n| react-router-dom | moderate | CVE-2026-53668 | v1 | React Router: Open redirect leading to XSS |\n| serialize-javascript | moderate | CVE-2026-34043 | v4, v3, v2, v1 | Serialize JavaScript has CPU Exhaustion Denial of Service via crafted array-like |\n| serialize-javascript | moderate | CVE-2024-11831 | v2 | Cross-site Scripting (XSS) in serialize-javascript |\n| smol-toml | moderate | GHSA-v3rj-xjv7-4jmq | v3, v1 | smol-toml: Denial of Service via TOML documents containing thousands of consecut |\n| tar | moderate | CVE-2026-53655 | v3, v1 | node-tar applies PAX size override to intermediary GNU long-name/long-link heade |\n| tar | moderate | CVE-2026-59871 | v3, v1 | node-tar: Process crash via PAX numeric path type confusion |\n| tar | moderate | CVE-2026-59875 | v3, v1 | node-tar: Uncaught Exception DoS via NUL byte in PAX path/linkpath records |\n| undici | moderate | CVE-2026-1525 | v3 | Undici has an HTTP Request/Response Smuggling issue |\n| undici | moderate | CVE-2026-1527 | v3 | Undici has CRLF Injection in undici via `upgrade` option |\n| undici | moderate | CVE-2026-9679 | v3 | undici vulnerable to HTTP header injection via Set-Cookie percent-decoding |\n| undici | moderate | CVE-2026-9678 | v3 | undici vulnerable to cross-user information disclosure via shared cache whitespa |\n| undici | moderate | CVE-2026-16728 | v3 | undici vulnerable to downstream response desynchronization via retry interceptor |\n| undici | moderate | CVE-2026-15157 | v3 | undici vulnerable to CRLF Injection via blob-like body 'type' property |\n| undici | moderate | CVE-2026-14643 | v3 | undici vulnerable to cross-user information disclosure via whitespace around equ |\n| undici | moderate | CVE-2026-16729 | v3 | undici vulnerable to cookie attribute injection via unsanitized domain and unpar |\n| uuid | moderate | CVE-2026-41907 | v4, v3, v2 | uuid: Missing buffer bounds check in v3/v5/v6 when buf is provided |\n| vite | moderate | CVE-2026-39365 | v1 | Vite Vulnerable to Path Traversal in Optimized Deps `.map` Handling |\n| vite | moderate | CVE-2026-53632 | v3, v1 | launch-editor: NTLMv2 hash disclosure via UNC path handling on Windows |\n| webpack | moderate | CVE-2024-43788 | v2 | Webpack's AutoPublicPathRuntimeModule has a DOM Clobbering Gadget that leads to |\n| webpack-dev-server | moderate | CVE-2025-30360 | v2 | webpack-dev-server users' source code may be stolen when they access a malicious |\n| webpack-dev-server | moderate | CVE-2025-30359 | v2 | webpack-dev-server users' source code may be stolen when they access a malicious |\n| webpack-dev-server | moderate | CVE-2026-6402 | v2 | webpack-dev-server vulnerable to cross-origin source code exposure on non-HTTPS |\n| webpack-dev-server | moderate | CVE-2026-9595 | v2 | webpack-dev-server vulnerable to HMR WebSocket interception via permissive user |\n| webpack-dev-server | moderate | CVE-2026-14620 | v3, v2 | webpack-dev-server vulnerable to cross-site request forgery via internal develop |\n| webpack-dev-server | moderate | CVE-2026-14631 | v3, v2 | webpack-dev-server vulnerable to denial of service via a malformed Host or Origi |\n| websocket-driver | moderate | CVE-2026-54490 | v3, v2 | websocket-driver: Resource limit bypass via message compression |\n| ws | moderate | CVE-2026-45736 | v3, v2 | ws: Uninitialized memory disclosure |\n| yaml | moderate | CVE-2026-33532 | v3, v2, v1 | yaml is vulnerable to Stack Overflow via deeply nested YAML collections |\n| @babel/core | low | CVE-2026-49356 | v4, v3, v2, v1 | @babel/core: Arbitrary File Read via sourceMappingURL Comment |\n| @tootallnate/once | low | CVE-2026-3449 | v3, v2, v1 | @tootallnate/once vulnerable to Incorrect Control Flow Scoping |\n| axios | low | CVE-2026-42040 | v3 | Axios: Null Byte Injection via Reverse-Encoding in AxiosURLSearchParams |\n| body-parser | low | CVE-2026-12590 | v3, v2 | body-parser vulnerable to denial of service when invalid limit value silently di |\n| diff | low | CVE-2026-24001 | v4, v3, v2 | jsdiff has a Denial of Service vulnerability in parsePatch and applyPatch |\n| fast-xml-parser | low | CVE-2026-27942 | v3, v2 | fast-xml-parser has stack overflow in XMLBuilder with preserveOrder |\n| handlebars | low | GHSA-442j-39wm-28r2 | v3, v1 | Handlebars.js has a Property Access Validation Bypass in container.lookup |\n| hono | low | GHSA-gq3j-xvxp-8hrf | v2 | Hono added timing comparison hardening in basicAuth and bearerAuth |\n| hono | low | CVE-2026-44459 | v2 | Hono has improper validation of NumericDate claims (exp, nbf, iat) in JWT verify |\n| hono | low | CVE-2026-71849 | v3, v2 | Hono: Proxy Helper does not remove response headers listed in the `Connection` h |\n| qs | low | CVE-2026-2391 | v2 | qs's arrayLimit bypass in comma parsing allows denial of service |\n| undici | low | CVE-2026-11525 | v3 | undici vulnerable to Set-Cookie SameSite attribute downgrade via permissive subs |\n| undici | low | CVE-2026-6733 | v3 | undici vulnerable to HTTP response queue poisoning via keep-alive socket reuse |\n| webpack | low | CVE-2025-68458 | v2 | webpack buildHttp: allowedUris allow-list bypass via URL userinfo (@) leading to |\n| webpack | low | CVE-2025-68157 | v2 | webpack buildHttp HttpUriPlugin allowedUris bypass via HTTP redirects → SSRF + c |\n",
|
|
344
|
+
"code": "# CVE Overview\n\n> For more security information, see [SECURITY.md](./SECURITY.md)\n\n## 1. Production Dependencies\n\n### Summary\n\n| Severity | v4 | v3 | v2 | v1 |\n| -------- | --: | --: | --: | --: |\n| critical | 0 | 0 | 0 | 0 |\n| high | 10 | 20 | 2 | 22 |\n| moderate | 2 | 16 | 2 | 7 |\n| low | 0 | 2 | 0 | 1 |\n| info | 0 | 0 | 0 | 0 |\n| unknown | 0 | 0 | 0 | 0 |\n\n### Vulnerabilities\n\n| Package | Severity | CVE | Affected Versions | Description |\n| ----------------------- | -------- | ------------------- | ----------------- | -------------------------------------------------------------------------------- |\n| @angular/common | high | CVE-2026-68945 | v3 | Angular: Cache-Key Ambiguity in HttpTransferCache Leading to Cross-Request Respo |\n| @angular/compiler | high | CVE-2026-69151 | v3 | Angular i18n: Cross-Site Scripting (XSS) via event-handler attributes |\n| @angular/core | high | CVE-2026-69151 | v3 | Angular i18n: Cross-Site Scripting (XSS) via event-handler attributes |\n| brace-expansion | high | CVE-2026-13149 | v1 | brace-expansion: DoS via exponential-time expansion of consecutive non-expanding |\n| brace-expansion | high | CVE-2026-14257 | v1 | brace-expansion: DoS via unbounded expansion length causing an out-of-memory pro |\n| brace-expansion | high | CVE-2026-69152 | v1 | brace-expansion: DoS via unbounded intermediate arrays, bypassing the CVE-2026-1 |\n| browserslist | high | CVE-2026-73089 | v1 | Browserslist: Unbounded memory growth (no cache eviction) via distinct query res |\n| browserslist | high | CVE-2026-73088 | v1 | Browserslist: Uncaught crash / prototype write via untrusted browserslist-stats. |\n| extract-zip | high | CVE-2026-56876 | v1 | extract-zip unvalidated symlink path traversal |\n| fast-uri | high | CVE-2026-18446 | v3, v1 | fast-uri vulnerable to host confusion via backslash authority introducer |\n| fast-uri | high | CVE-2026-75931 | v4, v1 | fast-uri vulnerable to host confusion via skipped IDN canonicalization on scheme |\n| fast-uri | high | CVE-2026-75975 | v4, v3, v1 | fast-uri vulnerable to server-side request forgery via malformed IPv6 normalizat |\n| fast-uri | high | CVE-2026-75899 | v4, v3, v1 | fast-uri vulnerable to server-side request forgery via repeated hostname percent |\n| fast-uri | high | CVE-2026-76172 | v4, v3, v1 | fast-uri vulnerable to host confusion via percent-encoded scheme normalization |\n| fast-uri | high | CVE-2026-16221 | v3 | fast-uri vulnerable to host confusion via literal backslash authority delimiter |\n| fast-uri | high | CVE-2026-13676 | v3 | fast-uri vulnerable to host confusion via failed IDN canonicalization |\n| find-my-way | high | CVE-2026-47219 | v3 | find-my-way: DDoS with HTTP2 |\n| image-size | high | CVE-2025-71330 | v4, v3, v2, v1 | image-size: ICNS parser allows denial of service through an infinite loop |\n| image-size | high | CVE-2025-71329 | v4, v3, v2, v1 | image-size: JXL and HEIF parsers allow denial of service through infinite loops |\n| immutable | high | CVE-2026-59879 | v3, v1 | Immutable.js `List` 32-bit trie overflow → unrecoverable DoS |\n| immutable | high | CVE-2026-59880 | v3, v1 | Immutable: Hash-collision algorithmic complexity denial of service in Immutable. |\n| ip-address | high | CVE-2026-69192 | v3 | ip-address: Address4 decodes leading-zero octets as decimal while resolvers deco |\n| js-yaml | high | GHSA-5p4m-2wfm-xmqj | v1 | JS-YAML: Quadratic CPU consumption in !!omap resolution (3.x and 4.x) — CVE-2026 |\n| linkify-it | high | CVE-2026-59887 | v3 | linkify-it: Quadratic-complexity DoS via the `mailto:` validator scan-loop on at |\n| lodash.pick | high | CVE-2020-8203 | v1 | Prototype Pollution in lodash |\n| minimatch | high | CVE-2026-27903 | v1 | minimatch has ReDoS: matchOne() combinatorial backtracking via multiple non-adja |\n| minimatch | high | CVE-2026-27904 | v1 | minimatch ReDoS: nested *() extglobs generate catastrophically backtracking regu |\n| nanoid | high | CVE-2026-67213 | v3, v1 | nanoid: custom generators can loop indefinitely when size is zero |\n| nanoid | high | CVE-2026-67214 | v3 | nanoid: non-secure generators can loop indefinitely with negative size |\n| postcss | high | CVE-2026-73646 | v3 | PostCSS: Path Traversal in Previous Source Map Auto-Loading (sourceMappingURL) l |\n| react-router | high | GHSA-qwww-vcr4-c8h2 | v3 | React Router: RSC Mode CSRF Bypass Allows Action Execution Before 400 Response |\n| serialize-javascript | high | GHSA-5c6j-r48x-rmvq | v1 | Serialize JavaScript is Vulnerable to RCE via RegExp.flags and Date.prototype.to |\n| @hono/node-server | moderate | GHSA-frvp-7c67-39w9 | v3 | Node.js Adapter for Hono: Path traversal in `serve-static` on Windows via encode |\n| brace-expansion | moderate | CVE-2026-45149 | v1 | brace-expansion: Large numeric range defeats documented `max` DoS protection |\n| dompurify | moderate | GHSA-55q2-fjhq-7xh7 | v1 | DOMPurify: IN_PLACE hook removal leaves a detached subtree executable, causing X |\n| fastify | moderate | CVE-2026-18504 | v3 | fastify vulnerable to schema validation bypass via root primitive coercion misma |\n| fastify | moderate | CVE-2026-16732 | v3 | fastify vulnerable to X-Forwarded-* spoofing under trustProxy hop-count |\n| hono | moderate | CVE-2026-59897 | v3 | Hono: API Gateway v1 adapter can drop a distinct repeated request header value d |\n| hono | moderate | CVE-2026-59896 | v3 | hono/jsx does not isolate context per request, leading to cross-request data dis |\n| hono | moderate | CVE-2026-59895 | v3 | Hono: Server-Side XSS via JSX Escaping Bypass in cx() Utility |\n| hono | moderate | CVE-2026-69207 | v3 | Hono: ReDoS in CORS middleware via Access-Control-Request-Headers |\n| hono | moderate | CVE-2026-71850 | v3 | Hono: `memo()` retains SSR output across requests, leading to cross-user data di |\n| hono | moderate | CVE-2026-71848 | v3 | Hono: Algorithmic Complexity DoS in Language Middleware |\n| ip-address | moderate | CVE-2026-69198 | v3 | ip-address: a CIDR suffix on the parsed address suppresses special-use classific |\n| ip-address | moderate | CVE-2026-54272 | v3 | ip-address: misclassification of IPv4-mapped/NAT64 IPv6 addresses can bypass SSR |\n| postcss | moderate | CVE-2026-69153 | v3 | PostCSS: incomplete fix of GHSA-6g55-p6wh-862q — attacker-controlled sourceMappi |\n| protobufjs | moderate | CVE-2026-59876 | v3 | protobufjs: Text Format string map parsing can mutate returned map object protot |\n| protobufjs | moderate | CVE-2026-59877 | v3 | protobufjs: Denial of Service via infinite loop in .proto option parsing |\n| qs | moderate | CVE-2026-8723 | v1 | qs has a remotely triggerable DoS: qs.stringify crashes with TypeError on null/u |\n| qs | moderate | CVE-2026-82562 | v4, v3, v2, v1 | qs array-limit bypass via bracket-key comma parsing |\n| qs | moderate | CVE-2026-82417 | v4, v3, v2, v1 | qs: Denial of Service via Attacker Controlled isBuffer |\n| react-router-dom | moderate | CVE-2026-53668 | v1 | React Router: Open redirect leading to XSS |\n| serialize-javascript | moderate | CVE-2026-34043 | v1 | Serialize JavaScript has CPU Exhaustion Denial of Service via crafted array-like |\n| body-parser | low | CVE-2026-12590 | v3 | body-parser vulnerable to denial of service when invalid limit value silently di |\n| hono | low | CVE-2026-71849 | v3 | Hono: Proxy Helper does not remove response headers listed in the `Connection` h |\n| postcss-selector-parser | low | CVE-2026-9358 | v1 | postcss-selector-parser allows denial of service through uncontrolled AST recurs |\n\n## 2. All Dependencies\n\n### Summary\n\n| Severity | v4 | v3 | v2 | v1 |\n| -------- | --: | --: | --: | --: |\n| critical | 1 | 9 | 4 | 5 |\n| high | 29 | 113 | 87 | 65 |\n| moderate | 19 | 80 | 68 | 26 |\n| low | 2 | 15 | 15 | 5 |\n| info | 0 | 0 | 0 | 0 |\n| unknown | 0 | 0 | 0 | 0 |\n\n### Vulnerabilities\n\n| Package | Severity | CVE | Affected Versions | Description |\n| ----------------------- | -------- | ------------------- | ----------------- | -------------------------------------------------------------------------------- |\n| basic-ftp | critical | CVE-2026-27699 | v3 | Basic FTP has Path Traversal Vulnerability in its downloadToDir() method |\n| fast-xml-parser | critical | CVE-2026-25896 | v3, v2 | fast-xml-parser has an entity encoding bypass via regex injection in DOCTYPE ent |\n| handlebars | critical | CVE-2026-33937 | v3, v1 | Handlebars.js has JavaScript Injection via AST Type Confusion |\n| happy-dom | critical | CVE-2025-61927 | v4 | Happy DOM: VM Context Escape can lead to Remote Code Execution |\n| locutus | critical | CVE-2026-25521 | v3, v1 | locutus is vulnerable to Prototype Pollution |\n| locutus | critical | CVE-2026-32304 | v3, v2, v1 | Locutus vulnerable to RCE via unsanitized input in create_function() |\n| seroval | critical | CVE-2026-59940 | v3, v2, v1 | seroval: `seroval.fromJSON()` Promise resolver type confusion invokes attacker-c |\n| shell-quote | critical | CVE-2026-9277 | v3 | shell-quote quote() does not escape newlines in object .op values |\n| tar | critical | CVE-2026-59873 | v3, v1 | node-tar: Decompression/parse DoS via unlimited input |\n| websocket-driver | critical | CVE-2026-54466 | v3, v2 | websocket-driver: Message corruption via abuse of protocol length headers |\n| @angular/common | high | CVE-2025-66035 | v1 | Angular is Vulnerable to XSRF Token Leakage via Protocol-Relative URLs in Angula |\n| @angular/common | high | CVE-2026-54268 | v4, v3, v2, v1 | @angular/common: Denial of Service (DoS) via OOM in Date Formatting (formatDate) |\n| @angular/common | high | CVE-2026-54266 | v4, v3, v2, v1 | @angular/common: Weak 32-Bit Cache Key Hashing in `HttpTransferCache` Leading to |\n| @angular/common | high | CVE-2026-50171 | v1 | @angular/common: Denial of Service (DoS) via OOM in Number Formatting (digitsInf |\n| @angular/common | high | CVE-2026-50170 | v1 | @angular/common: Information Leak via Default Caching of Credentialed Requests i |\n| @angular/common | high | CVE-2026-68945 | v4, v3, v2, v1 | Angular: Cache-Key Ambiguity in HttpTransferCache Leading to Cross-Request Respo |\n| @angular/compiler | high | CVE-2026-32635 | v1 | Angular vulnerable to XSS in i18n attribute bindings |\n| @angular/compiler | high | CVE-2026-22610 | v1 | Angular has XSS Vulnerability via Unsanitized SVG Script Attributes |\n| @angular/compiler | high | CVE-2025-66412 | v1 | Angular Stored XSS Vulnerability via SVG Animation, SVG URL and MathML Attribute |\n| @angular/compiler | high | CVE-2026-69151 | v4, v3, v2, v1 | Angular i18n: Cross-Site Scripting (XSS) via event-handler attributes |\n| @angular/core | high | CVE-2026-27970 | v1 | Angular i18n vulnerable to Cross-Site Scripting |\n| @angular/core | high | CVE-2026-32635 | v1 | Angular vulnerable to XSS in i18n attribute bindings |\n| @angular/core | high | CVE-2026-22610 | v1 | Angular has XSS Vulnerability via Unsanitized SVG Script Attributes |\n| @angular/core | high | CVE-2026-54267 | v4, v3, v2, v1 | Angular Client Hydration DOM Clobbering & Response-Cache Poisoning |\n| @angular/core | high | CVE-2026-69151 | v4, v3, v2, v1 | Angular i18n: Cross-Site Scripting (XSS) via event-handler attributes |\n| @hono/node-server | high | CVE-2026-29087 | v2 | @hono/node-server has authorization bypass for protected static paths via encode |\n| axios | high | CVE-2026-42043 | v3 | Axios: Incomplete Fix for CVE-2025-62718 — NO_PROXY Protection Bypassed via RFC |\n| axios | high | CVE-2026-42033 | v3 | Axios: Prototype Pollution Gadgets - Response Tampering, Data Exfiltration, and |\n| axios | high | CVE-2026-42035 | v3 | Axios: Header Injection via Prototype Pollution |\n| axios | high | CVE-2026-25639 | v3 | Axios is Vulnerable to Denial of Service via **proto** Key in mergeConfig |\n| axios | high | CVE-2026-42264 | v3 | Axios has prototype pollution read-side gadgets in HTTP adapter that allow crede |\n| axios | high | CVE-2026-44496 | v3 | Axios: Regular Expression Denial of Service (ReDoS) via Cookie Name Injection |\n| axios | high | CVE-2026-44488 | v3 | Allocation of Resources Without Limits or Throttling in Axios |\n| axios | high | CVE-2026-44487 | v3 | Axios: Proxy-Authorization Credential Leak to Origin Server Across HTTP-to-HTTPS |\n| axios | high | CVE-2026-44486 | v3 | Axios: Proxy-Authorization header leaks to redirect target when proxy is re-eval |\n| axios | high | CVE-2026-44495 | v3 | axios Vulnerable to Credential Theft and Response Hijacking via Prototype Pollut |\n| axios | high | CVE-2026-44494 | v3 | axios Vulnerable to Full Man-in-the-Middle via Prototype Pollution Gadget in `co |\n| basic-ftp | high | GHSA-6v7q-wjvx-w8wg | v3 | basic-ftp: Incomplete CRLF Injection Protection Allows Arbitrary FTP Command Exe |\n| basic-ftp | high | CVE-2026-41324 | v3 | basic-ftp vulnerable to denial of service via unbounded memory consumption in Cl |\n| basic-ftp | high | CVE-2026-44240 | v3 | basic-ftp allows a malicious FTP server to cause client-side denial of service v |\n| brace-expansion | high | CVE-2026-13149 | v3, v2, v1 | brace-expansion: DoS via exponential-time expansion of consecutive non-expanding |\n| brace-expansion | high | CVE-2026-14257 | v3, v2, v1 | brace-expansion: DoS via unbounded expansion length causing an out-of-memory pro |\n| brace-expansion | high | CVE-2026-69152 | v3, v2, v1 | brace-expansion: DoS via unbounded intermediate arrays, bypassing the CVE-2026-1 |\n| braces | high | CVE-2024-4068 | v3, v2, v1 | Uncontrolled resource consumption in braces |\n| browserslist | high | CVE-2026-73089 | v3, v2, v1 | Browserslist: Unbounded memory growth (no cache eviction) via distinct query res |\n| browserslist | high | CVE-2026-73088 | v3, v2, v1 | Browserslist: Uncaught crash / prototype write via untrusted browserslist-stats. |\n| deepmerge-ts | high | CVE-2026-40345 | v4, v3, v2 | DeepmergeTS has stack exhaustion when merging recursive object graphs |\n| engine.io | high | CVE-2026-59725 | v3, v2 | Socket.IO: Engine.IO Polling Transport Connection Exhaustion |\n| engine.io | high | CVE-2026-59724 | v3, v2 | Socket.IO: Engine.IO WebTransport SID DoS |\n| express-rate-limit | high | CVE-2026-30827 | v2 | express-rate-limit: IPv4-mapped IPv6 addresses bypass per-client rate limiting o |\n| extract-zip | high | CVE-2026-56876 | v4, v3, v2, v1 | extract-zip unvalidated symlink path traversal |\n| fast-uri | high | CVE-2026-18446 | v3, v2, v1 | fast-uri vulnerable to host confusion via backslash authority introducer |\n| fast-uri | high | CVE-2026-75931 | v4, v1 | fast-uri vulnerable to host confusion via skipped IDN canonicalization on scheme |\n| fast-uri | high | CVE-2026-75975 | v4, v3, v2, v1 | fast-uri vulnerable to server-side request forgery via malformed IPv6 normalizat |\n| fast-uri | high | CVE-2026-75899 | v4, v3, v1 | fast-uri vulnerable to server-side request forgery via repeated hostname percent |\n| fast-uri | high | CVE-2026-76172 | v4, v3, v2, v1 | fast-uri vulnerable to host confusion via percent-encoded scheme normalization |\n| fast-uri | high | CVE-2026-16221 | v3, v2 | fast-uri vulnerable to host confusion via literal backslash authority delimiter |\n| fast-uri | high | CVE-2026-6321 | v2 | fast-uri vulnerable to path traversal via percent-encoded dot segments |\n| fast-uri | high | CVE-2026-13676 | v3, v2 | fast-uri vulnerable to host confusion via failed IDN canonicalization |\n| fast-uri | high | CVE-2026-6322 | v2 | fast-uri vulnerable to host confusion via percent-encoded authority delimiters |\n| fast-xml-parser | high | CVE-2026-25128 | v3, v2 | fast-xml-parser has RangeError DoS Numeric Entities Bug |\n| fast-xml-parser | high | CVE-2026-26278 | v3, v2 | fast-xml-parser affected by DoS through entity expansion in DOCTYPE (no expansio |\n| fast-xml-parser | high | CVE-2026-33036 | v3, v2 | fast-xml-parser affected by numeric entity expansion bypassing all entity expans |\n| find-my-way | high | CVE-2026-47219 | v3 | find-my-way: DDoS with HTTP2 |\n| flatted | high | CVE-2026-32141 | v3, v2 | flatted vulnerable to unbounded recursion DoS in parse() revive phase |\n| flatted | high | CVE-2026-33228 | v3, v2 | Prototype Pollution via parse() in NodeJS flatted |\n| form-data | high | CVE-2026-12143 | v3, v2, v1 | form-data: CRLF injection in form-data via unescaped multipart field names and f |\n| handlebars | high | CVE-2026-33938 | v3, v1 | Handlebars.js has JavaScript Injection via AST Type Confusion by tampering @part |\n| handlebars | high | CVE-2026-33940 | v3, v1 | Handlebars.js has JavaScript Injection via AST Type Confusion when passing an ob |\n| handlebars | high | CVE-2026-33939 | v3, v1 | Handlebars.js has Denial of Service via Malformed Decorator Syntax in Template C |\n| handlebars | high | CVE-2026-33941 | v3, v1 | Handlebars.js has JavaScript Injection in CLI Precompiler via Unescaped Names an |\n| happy-dom | high | CVE-2026-34226 | v4 | Happy DOM's fetch credentials include uses page-origin cookies instead of target |\n| happy-dom | high | CVE-2026-33943 | v4 | Happy DOM ECMAScriptModuleCompiler: unsanitized export names are interpolated as |\n| hono | high | CVE-2026-29045 | v2 | Hono vulnerable to arbitrary file access via serveStatic vulnerability |\n| hono | high | CVE-2026-54290 | v2 | hono: CORS Middleware reflects any Origin with credentials when `origin` default |\n| http-proxy-middleware | high | CVE-2026-55603 | v3 | http-proxy-middleware: multipart/form-data field injection via unescaped CRLF in |\n| image-size | high | CVE-2025-71330 | v4, v3, v2, v1 | image-size: ICNS parser allows denial of service through an infinite loop |\n| image-size | high | CVE-2025-71329 | v4, v3, v2, v1 | image-size: JXL and HEIF parsers allow denial of service through infinite loops |\n| immutable | high | CVE-2026-59879 | v3, v2, v1 | Immutable.js `List` 32-bit trie overflow → unrecoverable DoS |\n| immutable | high | CVE-2026-59880 | v3, v2, v1 | Immutable: Hash-collision algorithmic complexity denial of service in Immutable. |\n| immutable | high | CVE-2026-29063 | v2 | Immutable is vulnerable to Prototype Pollution |\n| ip-address | high | CVE-2026-69192 | v3, v2 | ip-address: Address4 decodes leading-zero octets as decimal while resolvers deco |\n| js-yaml | high | GHSA-5p4m-2wfm-xmqj | v3, v2, v1 | JS-YAML: Quadratic CPU consumption in !!omap resolution (3.x and 4.x) — CVE-2026 |\n| js-yaml | high | CVE-2026-59869 | v3, v2 | js-yaml: YAML merge-key chains can force quadratic CPU consumption |\n| linkify-it | high | CVE-2026-59887 | v3 | linkify-it: Quadratic-complexity DoS via the `mailto:` validator scan-loop on at |\n| locutus | high | CVE-2026-29091 | v3, v2, v1 | locutus call_user_func_array vulnerable to Remote Code Execution (RCE) due to Co |\n| lodash | high | CVE-2026-4800 | v3 | lodash vulnerable to Code Injection via `_.template` imports key names |\n| lodash.pick | high | CVE-2020-8203 | v2, v1 | Prototype Pollution in lodash |\n| minimatch | high | CVE-2026-27903 | v3, v2, v1 | minimatch has ReDoS: matchOne() combinatorial backtracking via multiple non-adja |\n| minimatch | high | CVE-2026-27904 | v3, v2, v1 | minimatch ReDoS: nested *() extglobs generate catastrophically backtracking regu |\n| minimatch | high | CVE-2026-26996 | v3, v2 | minimatch has a ReDoS via repeated wildcards with non-matching literal in patter |\n| nanoid | high | CVE-2026-67213 | v3, v1 | nanoid: custom generators can loop indefinitely when size is zero |\n| nanoid | high | CVE-2026-67214 | v3 | nanoid: non-secure generators can loop indefinitely with negative size |\n| nanoid | high | CVE-2026-73086 | v3 | nanoid: Integer Overflow or Wraparound |\n| node-forge | high | CVE-2026-33896 | v2 | Forge has a basicConstraints bypass in its certificate chain verification (RFC 5 |\n| node-forge | high | CVE-2026-33895 | v2 | Forge has signature forgery in Ed25519 due to missing S > L check |\n| node-forge | high | CVE-2026-33891 | v2 | Forge has Denial of Service via Infinite Loop in BigInteger.modInverse() with Ze |\n| node-forge | high | CVE-2026-33894 | v2 | Forge has signature forgery in RSA-PKCS due to ASN.1 extra field |\n| nx | high | CVE-2026-71476 | v3, v1 | Nx: Zip-Slip in the self-hosted remote cache |\n| pacote | high | CVE-2026-9496 | v3, v2, v1 | pacote is vulnerable to Denial of Service (DoS) via the addGitSha function |\n| path-to-regexp | high | CVE-2026-4867 | v3, v2 | path-to-regexp vulnerable to Regular Expression Denial of Service via multiple r |\n| path-to-regexp | high | CVE-2026-4926 | v2 | path-to-regexp vulnerable to Denial of Service via sequential optional groups |\n| piscina | high | CVE-2026-55388 | v3 | piscina: Prototype Pollution Gadget → RCE via inherited options.filename |\n| postcss | high | CVE-2026-45623 | v4, v3, v2 | PostCSS: Arbitrary file read and information disclosure via attacker-controlled |\n| postcss | high | CVE-2026-73646 | v4, v3, v2 | PostCSS: Path Traversal in Previous Source Map Auto-Loading (sourceMappingURL) l |\n| react-router | high | GHSA-qwww-vcr4-c8h2 | v3 | React Router: RSC Mode CSRF Bypass Allows Action Execution Before 400 Response |\n| rollup | high | CVE-2026-27606 | v1 | Rollup 4 has Arbitrary File Write via Path Traversal |\n| semver | high | CVE-2022-25883 | v2 | semver vulnerable to Regular Expression Denial of Service |\n| serialize-javascript | high | GHSA-5c6j-r48x-rmvq | v4, v3, v2, v1 | Serialize JavaScript is Vulnerable to RCE via RegExp.flags and Date.prototype.to |\n| shell-quote | high | CVE-2026-13311 | v3 | shell-quote: Quadratic-complexity Denial of Service in `parse()` (CWE-407) |\n| sigstore | high | CVE-2026-48815 | v3, v2, v1 | sigstore's `certificateOIDs` verification constraints are silently dropped and n |\n| socket.io-parser | high | CVE-2026-33151 | v3, v2 | socket.io allows an unbounded number of binary attachments |\n| socket.io-parser | high | CVE-2026-69185 | v3, v2 | Socket.IO: Zero-attachment Memory Exhaustion |\n| svgo | high | CVE-2026-29074 | v3, v2, v1 | SVGO DoS through entity expansion in DOCTYPE (Billion Laughs) |\n| svgo | high | CVE-2026-73650 | v3, v2, v1 | SVGO removeScripts plugin leaves some executable scripts intact |\n| tar | high | CVE-2026-24842 | v1 | node-tar Vulnerable to Arbitrary File Creation/Overwrite via Hardlink Path Trave |\n| tar | high | CVE-2026-23745 | v1 | node-tar is Vulnerable to Arbitrary File Overwrite and Symlink Poisoning via Ins |\n| tar | high | CVE-2026-26960 | v1 | Arbitrary File Read/Write via Hardlink Target Escape Through Symlink Chain in no |\n| tar | high | CVE-2026-29786 | v1 | tar has Hardlink Path Traversal via Drive-Relative Linkpath |\n| tar | high | CVE-2026-31802 | v1 | node-tar Symlink Path Traversal via Drive-Relative Linkpath |\n| tar | high | CVE-2026-23950 | v1 | Race Condition in node-tar Path Reservations via Unicode Ligature Collisions on |\n| tar | high | CVE-2026-59874 | v3, v1 | node-tar: Negative tar entry size causes infinite loop in archive replace |\n| tar | high | CVE-2026-73566 | v3, v2, v1 | node-tar: Uncontrolled recursion in mapHas/filesFilter allows uncatchable stack- |\n| tmp | high | CVE-2026-44705 | v3, v2 | tmp has Path Traversal via unsanitized prefix/postfix that enables directory esc |\n| undici | high | CVE-2026-1528 | v3 | Undici: Malicious WebSocket 64-bit length overflows parser and crashes the clien |\n| undici | high | CVE-2026-1526 | v3 | Undici has Unbounded Memory Consumption in WebSocket permessage-deflate Decompre |\n| undici | high | CVE-2026-2229 | v3 | Undici has Unhandled Exception in WebSocket Client Due to Invalid server_max_win |\n| undici | high | CVE-2026-9697 | v3 | undici vulnerable to TLS certificate validation bypass via dropped requestTls in |\n| undici | high | CVE-2026-12151 | v3 | undici WebSocket client vulnerable to denial of service via fragment count bypas |\n| undici | high | CVE-2026-6734 | v3 | undici vulnerable to cross-origin request routing via SOCKS5 proxy pool reuse |\n| undici | high | CVE-2026-13697 | v3 | undici vulnerable to cross-user information disclosure and parse-time crash via |\n| vite | high | CVE-2026-39364 | v1 | Vite: `server.fs.deny` bypassed with queries |\n| vite | high | CVE-2026-39363 | v1 | Vite Vulnerable to Arbitrary File Read via Vite Dev Server WebSocket |\n| vite | high | CVE-2026-53571 | v3, v1 | vite: `server.fs.deny` bypass on Windows alternate paths |\n| ws | high | CVE-2026-48779 | v3, v2, v1 | ws: Memory exhaustion DoS from tiny fragments and data chunks |\n| @angular/compiler | moderate | CVE-2026-54265 | v4, v3, v2, v1 | @angular/compiler: Two-Way Property Binding Sanitization Bypass (XSS) |\n| @angular/compiler | moderate | CVE-2026-50557 | v4, v1 | Angular: Template and Attribute Namespace Sanitization Bypass (XSS) |\n| @angular/core | moderate | CVE-2026-50557 | v4, v1 | Angular: Template and Attribute Namespace Sanitization Bypass (XSS) |\n| @angular/core | moderate | CVE-2026-52725 | v4, v1 | @angular/core: Angular Template and Dynamic Component Namespace Bypass leading t |\n| @hono/node-server | moderate | CVE-2026-39406 | v2 | @hono/node-server: Middleware bypass via repeated slashes in serveStatic |\n| @hono/node-server | moderate | GHSA-frvp-7c67-39w9 | v3, v2 | Node.js Adapter for Hono: Path traversal in `serve-static` on Windows via encode |\n| @humanfs/node | moderate | GHSA-p498-v437-472g | v3 | humanfs: Recursive copy follows symlinked files and copies data from outside the |\n| @opentelemetry/core | moderate | CVE-2026-54285 | v1 | OpenTelemetry Core: Unbounded memory allocation in W3C Baggage propagation |\n| @sigstore/core | moderate | CVE-2026-48758 | v3, v2, v1 | @sigstore/core has DSSE payloadType type-binding failure |\n| @xmldom/xmldom | moderate | CVE-2026-83610 | v4 | xmldom: XML fragment injection via invalid EntityReference.nodeName during requi |\n| ajv | moderate | CVE-2025-69873 | v3, v2 | ajv has ReDoS when using `$data` option |\n| axios | moderate | CVE-2025-62718 | v3 | Axios has a NO_PROXY Hostname Normalization Bypass that Leads to SSRF |\n| axios | moderate | CVE-2026-42041 | v3 | Axios: Authentication Bypass via Prototype Pollution Gadget in `validateStatus` |\n| axios | moderate | CVE-2026-42044 | v3 | Axios: Invisible JSON Response Tampering via Prototype Pollution Gadget in `pars |\n| axios | moderate | CVE-2026-42037 | v3 | Axios: CRLF Injection in multipart/form-data body via unsanitized blob.type in f |\n| axios | moderate | CVE-2026-42038 | v3 | Axios: no_proxy bypass via IP alias allows SSRF |\n| axios | moderate | CVE-2026-42034 | v3 | Axios' HTTP adapter-streamed uploads bypass maxBodyLength when maxRedirects: 0 |\n| axios | moderate | CVE-2026-42036 | v3 | Axios: HTTP adapter streamed responses bypass maxContentLength |\n| axios | moderate | CVE-2026-42042 | v3 | Axios: XSRF Token Cross-Origin Leakage via Prototype Pollution Gadget in `withXS |\n| axios | moderate | CVE-2026-40175 | v3 | Axios has Unrestricted Cloud Metadata Exfiltration via Header Injection Chain |\n| axios | moderate | CVE-2026-42039 | v3 | Axios: unbounded recursion in toFormData causes DoS via deeply nested request da |\n| axios | moderate | CVE-2026-44490 | v3 | axios has DoS & Header Injection via Prototype Pollution Read-Side Gadgets in ax |\n| axios | moderate | CVE-2026-67316 | v3 | Axios: Prototype pollution gadgets can alter axios request construction |\n| axios | moderate | CVE-2026-67312 | v3 | Axios: Deep formToJSON Key Recursion Can Cause Denial of Service |\n| axios | moderate | CVE-2026-67319 | v3 | Axios: Nested axios option objects can consume polluted prototype values |\n| axios | moderate | CVE-2026-67317 | v3 | Axios: Fetch adapter `ReadableStream` uploads bypass `maxBodyLength` |\n| axios | moderate | CVE-2026-67313 | v3 | Axios: Excessive recursion in formDataToJSON can cause denial of service |\n| brace-expansion | moderate | CVE-2026-45149 | v3, v2, v1 | brace-expansion: Large numeric range defeats documented `max` DoS protection |\n| brace-expansion | moderate | CVE-2026-33750 | v3, v2 | brace-expansion: Zero-step sequence causes process hang and memory exhaustion |\n| decode-uri-component | moderate | CVE-2026-45822 | v3, v2, v1 | decode-uri-component: Denial of service via exponential decoding of malformed pe |\n| dompurify | moderate | GHSA-55q2-fjhq-7xh7 | v1 | DOMPurify: IN_PLACE hook removal leaves a detached subtree executable, causing X |\n| ejs | moderate | CVE-2024-33883 | v2 | ejs lacks certain pollution protection |\n| esbuild | moderate | GHSA-67mh-4wv8-2f99 | v2 | esbuild enables any website to send any requests to the development server and r |\n| fast-xml-parser | moderate | CVE-2026-33349 | v3, v2 | Entity Expansion Limits Bypassed When Set to Zero Due to JavaScript Falsy Evalua |\n| fast-xml-parser | moderate | CVE-2026-41650 | v3, v2 | fast-xml-parser XMLBuilder: XML Comment and CDATA Injection via Unescaped Delimi |\n| fastify | moderate | CVE-2026-18504 | v3 | fastify vulnerable to schema validation bypass via root primitive coercion misma |\n| fastify | moderate | CVE-2026-16732 | v3 | fastify vulnerable to X-Forwarded-* spoofing under trustProxy hop-count |\n| file-type | moderate | CVE-2026-31808 | v4 | file-type affected by infinite loop in ASF parser on malformed input with zero-s |\n| handlebars | moderate | CVE-2026-33916 | v3, v1 | Handlebars.js has Prototype Pollution Leading to XSS through Partial Template In |\n| handlebars | moderate | GHSA-7rx3-28cr-v5wh | v3, v1 | Handlebars.js has a Prototype Method Access Control Gap via Missing __lookupSett |\n| hono | moderate | CVE-2026-29086 | v2 | Hono Vulnerable to Cookie Attribute Injection via Unsanitized domain and path in |\n| hono | moderate | CVE-2026-29085 | v2 | Hono Vulnerable to SSE Control Field Injection via CR/LF in writeSSE() |\n| hono | moderate | GHSA-v8w9-8mx6-g223 | v2 | Hono vulnerable to Prototype Pollution possible through **proto** key allowed in |\n| hono | moderate | GHSA-26pp-8wgv-hjvm | v2 | Hono missing validation of cookie name on write path in setCookie() |\n| hono | moderate | CVE-2026-39410 | v2 | Hono: Non-breaking space prefix bypass in cookie name handling in getCookie() |\n| hono | moderate | CVE-2026-39408 | v2 | Hono: Path traversal in toSSG() allows writing files outside the output director |\n| hono | moderate | CVE-2026-39407 | v2 | Hono: Middleware bypass via repeated slashes in serveStatic |\n| hono | moderate | CVE-2026-39409 | v2 | Hono has incorrect IP matching in ipRestriction() for IPv4-mapped IPv6 addresses |\n| hono | moderate | CVE-2026-44458 | v2 | Hono has CSS Declaration Injection via Style Object Values in JSX SSR |\n| hono | moderate | CVE-2026-44457 | v2 | Hono's Cache Middleware ignores Vary: Authorization / Vary: Cookie leading to cr |\n| hono | moderate | CVE-2026-44456 | v2 | Hono: bodyLimit() can be bypassed for chunked / unknown-length requests |\n| hono | moderate | CVE-2026-44455 | v2 | hono/jsx has Unvalidated JSX Tag Names that May Allow HTML Injection |\n| hono | moderate | CVE-2026-47674 | v2 | Hono: IP Restriction bypasses static deny rules for non-canonical IPv6 |\n| hono | moderate | CVE-2026-47675 | v2 | Hono: Cookie helper does not sanitize sameSite and priority, allowing Set-Cookie |\n| hono | moderate | CVE-2026-47673 | v2 | Hono: JWT middleware accepts any Authorization scheme, not only Bearer |\n| hono | moderate | CVE-2026-47676 | v2 | Hono: app.mount() strips mount prefix using undecoded path, causing incorrect ro |\n| hono | moderate | CVE-2026-56761 | v2 | hono Improperly Handles JSX Attribute Names Allows HTML Injection in hono/jsx SS |\n| hono | moderate | CVE-2026-54288 | v2 | hono: Body Limit Middleware can be bypassed on AWS Lambda by understating `Conte |\n| hono | moderate | CVE-2026-54289 | v2 | hono: Lambda@Edge adapter keeps only the last value of a repeated request header |\n| hono | moderate | CVE-2026-54286 | v2 | hono: Path traversal in `serve-static` on Windows via encoded backslash (`%5C`) |\n| hono | moderate | CVE-2026-54287 | v2 | hono: AWS Lambda adapter merges multiple `Set-Cookie` headers into one value, dr |\n| hono | moderate | CVE-2026-59897 | v3, v2 | Hono: API Gateway v1 adapter can drop a distinct repeated request header value d |\n| hono | moderate | CVE-2026-59895 | v3, v2 | Hono: Server-Side XSS via JSX Escaping Bypass in cx() Utility |\n| hono | moderate | CVE-2026-69207 | v3, v2 | Hono: ReDoS in CORS middleware via Access-Control-Request-Headers |\n| hono | moderate | CVE-2026-71850 | v3, v2 | Hono: `memo()` retains SSR output across requests, leading to cross-user data di |\n| hono | moderate | CVE-2026-59896 | v3 | hono/jsx does not isolate context per request, leading to cross-request data dis |\n| hono | moderate | CVE-2026-71848 | v3 | Hono: Algorithmic Complexity DoS in Language Middleware |\n| http-proxy-middleware | moderate | CVE-2026-55602 | v3, v2 | http-proxy-middleware `router` host+path substring matching allows Host-header-d |\n| ip-address | moderate | CVE-2026-42338 | v2 | ip-address has XSS in Address6 HTML-emitting methods |\n| ip-address | moderate | CVE-2026-69198 | v3 | ip-address: a CIDR suffix on the parsed address suppresses special-use classific |\n| ip-address | moderate | CVE-2026-54272 | v3 | ip-address: misclassification of IPv4-mapped/NAT64 IPv6 addresses can bypass SSR |\n| js-yaml | moderate | CVE-2025-64718 | v2 | js-yaml has prototype pollution in merge (<<) |\n| js-yaml | moderate | CVE-2026-53550 | v3, v2 | JS-YAML: Quadratic-complexity DoS in merge key handling via repeated aliases |\n| launch-editor | moderate | CVE-2026-53632 | v3, v2 | launch-editor: NTLMv2 hash disclosure via UNC path handling on Windows |\n| locutus | moderate | CVE-2026-33993 | v3, v2, v1 | Locutus has Prototype Pollution via **proto** Key Injection in unserialize() |\n| locutus | moderate | CVE-2026-33994 | v2 | Locutus Prototype Pollution due to incomplete fix for CVE-2026-25521 |\n| lodash | moderate | CVE-2026-2950 | v3 | lodash vulnerable to Prototype Pollution via array path bypass in `_.unset` and |\n| micromatch | moderate | CVE-2024-4067 | v3, v2, v1 | Regular Expression Denial of Service (ReDoS) in micromatch |\n| nx | moderate | CVE-2026-54753 | v3, v1 | `nx graph` dev server permissive CORS policy |\n| path-to-regexp | moderate | CVE-2026-4923 | v2 | path-to-regexp vulnerable to Regular Expression Denial of Service via multiple w |\n| postcss | moderate | CVE-2026-41305 | v4, v3, v2 | PostCSS has XSS via Unescaped </style> in its CSS Stringify Output |\n| postcss | moderate | CVE-2026-69153 | v4, v3, v2 | PostCSS: incomplete fix of GHSA-6g55-p6wh-862q — attacker-controlled sourceMappi |\n| protobufjs | moderate | CVE-2026-59876 | v3 | protobufjs: Text Format string map parsing can mutate returned map object protot |\n| protobufjs | moderate | CVE-2026-59877 | v3 | protobufjs: Denial of Service via infinite loop in .proto option parsing |\n| qs | moderate | CVE-2026-8723 | v3, v2, v1 | qs has a remotely triggerable DoS: qs.stringify crashes with TypeError on null/u |\n| qs | moderate | CVE-2026-82562 | v4, v3, v2, v1 | qs array-limit bypass via bracket-key comma parsing |\n| qs | moderate | CVE-2026-82417 | v4, v3, v2, v1 | qs: Denial of Service via Attacker Controlled isBuffer |\n| qs | moderate | CVE-2025-15284 | v2 | qs's arrayLimit bypass in its bracket notation allows DoS via memory exhaustion |\n| react-router-dom | moderate | CVE-2026-53668 | v1 | React Router: Open redirect leading to XSS |\n| serialize-javascript | moderate | CVE-2026-34043 | v4, v3, v2, v1 | Serialize JavaScript has CPU Exhaustion Denial of Service via crafted array-like |\n| serialize-javascript | moderate | CVE-2024-11831 | v2 | Cross-site Scripting (XSS) in serialize-javascript |\n| smol-toml | moderate | GHSA-v3rj-xjv7-4jmq | v3, v1 | smol-toml: Denial of Service via TOML documents containing thousands of consecut |\n| tar | moderate | CVE-2026-53655 | v3, v1 | node-tar applies PAX size override to intermediary GNU long-name/long-link heade |\n| tar | moderate | CVE-2026-59871 | v3, v1 | node-tar: Process crash via PAX numeric path type confusion |\n| tar | moderate | CVE-2026-59875 | v3, v1 | node-tar: Uncaught Exception DoS via NUL byte in PAX path/linkpath records |\n| undici | moderate | CVE-2026-1525 | v3 | Undici has an HTTP Request/Response Smuggling issue |\n| undici | moderate | CVE-2026-1527 | v3 | Undici has CRLF Injection in undici via `upgrade` option |\n| undici | moderate | CVE-2026-9679 | v3 | undici vulnerable to HTTP header injection via Set-Cookie percent-decoding |\n| undici | moderate | CVE-2026-9678 | v3 | undici vulnerable to cross-user information disclosure via shared cache whitespa |\n| undici | moderate | CVE-2026-16728 | v3 | undici vulnerable to downstream response desynchronization via retry interceptor |\n| undici | moderate | CVE-2026-15157 | v3 | undici vulnerable to CRLF Injection via blob-like body 'type' property |\n| undici | moderate | CVE-2026-14643 | v3 | undici vulnerable to cross-user information disclosure via whitespace around equ |\n| undici | moderate | CVE-2026-16729 | v3 | undici vulnerable to cookie attribute injection via unsanitized domain and unpar |\n| uuid | moderate | CVE-2026-41907 | v4, v3, v2 | uuid: Missing buffer bounds check in v3/v5/v6 when buf is provided |\n| vite | moderate | CVE-2026-39365 | v1 | Vite Vulnerable to Path Traversal in Optimized Deps `.map` Handling |\n| vite | moderate | CVE-2026-53632 | v3, v1 | launch-editor: NTLMv2 hash disclosure via UNC path handling on Windows |\n| webpack | moderate | CVE-2024-43788 | v2 | Webpack's AutoPublicPathRuntimeModule has a DOM Clobbering Gadget that leads to |\n| webpack-dev-server | moderate | CVE-2025-30360 | v2 | webpack-dev-server users' source code may be stolen when they access a malicious |\n| webpack-dev-server | moderate | CVE-2025-30359 | v2 | webpack-dev-server users' source code may be stolen when they access a malicious |\n| webpack-dev-server | moderate | CVE-2026-6402 | v2 | webpack-dev-server vulnerable to cross-origin source code exposure on non-HTTPS |\n| webpack-dev-server | moderate | CVE-2026-9595 | v2 | webpack-dev-server vulnerable to HMR WebSocket interception via permissive user |\n| webpack-dev-server | moderate | CVE-2026-14620 | v3, v2 | webpack-dev-server vulnerable to cross-site request forgery via internal develop |\n| webpack-dev-server | moderate | CVE-2026-14631 | v3, v2 | webpack-dev-server vulnerable to denial of service via a malformed Host or Origi |\n| websocket-driver | moderate | CVE-2026-54490 | v3, v2 | websocket-driver: Resource limit bypass via message compression |\n| ws | moderate | CVE-2026-45736 | v3, v2 | ws: Uninitialized memory disclosure |\n| yaml | moderate | CVE-2026-33532 | v3, v2, v1 | yaml is vulnerable to Stack Overflow via deeply nested YAML collections |\n| @babel/core | low | CVE-2026-49356 | v4, v3, v2, v1 | @babel/core: Arbitrary File Read via sourceMappingURL Comment |\n| @tootallnate/once | low | CVE-2026-3449 | v3, v2, v1 | @tootallnate/once vulnerable to Incorrect Control Flow Scoping |\n| axios | low | CVE-2026-42040 | v3 | Axios: Null Byte Injection via Reverse-Encoding in AxiosURLSearchParams |\n| body-parser | low | CVE-2026-12590 | v3, v2 | body-parser vulnerable to denial of service when invalid limit value silently di |\n| diff | low | CVE-2026-24001 | v4, v3, v2 | jsdiff has a Denial of Service vulnerability in parsePatch and applyPatch |\n| fast-xml-parser | low | CVE-2026-27942 | v3, v2 | fast-xml-parser has stack overflow in XMLBuilder with preserveOrder |\n| handlebars | low | GHSA-442j-39wm-28r2 | v3, v1 | Handlebars.js has a Property Access Validation Bypass in container.lookup |\n| hono | low | GHSA-gq3j-xvxp-8hrf | v2 | Hono added timing comparison hardening in basicAuth and bearerAuth |\n| hono | low | CVE-2026-44459 | v2 | Hono has improper validation of NumericDate claims (exp, nbf, iat) in JWT verify |\n| hono | low | CVE-2026-71849 | v3, v2 | Hono: Proxy Helper does not remove response headers listed in the `Connection` h |\n| postcss-selector-parser | low | CVE-2026-9358 | v3, v2, v1 | postcss-selector-parser allows denial of service through uncontrolled AST recurs |\n| qs | low | CVE-2026-2391 | v2 | qs's arrayLimit bypass in comma parsing allows denial of service |\n| undici | low | CVE-2026-11525 | v3 | undici vulnerable to Set-Cookie SameSite attribute downgrade via permissive subs |\n| undici | low | CVE-2026-6733 | v3 | undici vulnerable to HTTP response queue poisoning via keep-alive socket reuse |\n| webpack | low | CVE-2025-68458 | v2 | webpack buildHttp: allowedUris allow-list bypass via URL userinfo (@) leading to |\n| webpack | low | CVE-2025-68157 | v2 | webpack buildHttp HttpUriPlugin allowedUris bypass via HTTP redirects → SSRF + c |\n",
|
|
345
345
|
"kind": "doc"
|
|
346
346
|
},
|
|
347
347
|
{
|
|
@@ -453,7 +453,7 @@
|
|
|
453
453
|
"group": "docs",
|
|
454
454
|
"name": "RENOVATE",
|
|
455
455
|
"path": "docs/RENOVATE.md",
|
|
456
|
-
"code": "# Renovate — Automated Dependency Updates\n\nThis document is the outcome of issue [#10270](https://github.com/public-ui/kolibri/issues/10270)\n(_renovate vs npm-check-updates vs dependabot_). It contains:\n\n1. a comparison of the three candidate tools,\n2. a description of the exemplary [`renovate.json`](../renovate.json) that ships with this repo,\n3. how to enable Renovate, and\n4. the migration checklist for retiring the current tooling.\n\n> **Status:** The `renovate.json` and a self-hosted runner workflow\n> ([`.github/workflows/renovate.yml`](../.github/workflows/renovate.yml)) are committed as an\n> **exemplary, ready-to-run setup**. Renovate stays **idle** until that workflow runs — either on its\n> weekly schedule or via the manual **Run workflow** button (see [Enabling Renovate](#enabling-renovate)).\n> Until then the existing Dependabot + npm-check-updates automation stays in charge.\n\n---\n\n## 1. Tool comparison\n\nKoliBri is a **pnpm-workspace monorepo** with 30+ packages, several intentionally pinned major\nlines (Angular `v19`/`v20`/`v21`, React 18/19, Stencil 4, ESLint 9) and four maintained branches\n(`develop`, `release/3`, `release/2`, `release/1`). That shapes the comparison:\n\n| Capability | **Renovate** | Dependabot | npm-check-updates (ncu) |\n| -------------------------------------------- | :----------------------: | :---------------------------------: | :-----------------------: |\n| pnpm-workspace aware | ✅ native | ⚠️ partial | ❌ manual (per-package) |\n| One PR grouping related packages | ✅ fully configurable | ⚠️ `groups:` only | ❌ none |\n| Hold a package on a specific major line | ✅ per-folder rules | ⚠️ `ignore` (global) | ⚠️ `-x` exclude (global) |\n| GitHub Actions updates | ✅ | ✅ | ❌ |\n| Lockfile-only refresh | ✅ `lockFileMaintenance` | ⚠️ limited | ❌ (needs `pnpm install`) |\n| Automerge (per update type) | ✅ | ⚠️ limited | ❌ |\n| Multi-base-branch (release/\\*) support | ✅ `baseBranchPatterns` | ✅ `target-branch` (one entry each) | ⚠️ matrix in a workflow |\n| Security / vulnerability remediation | ✅ OSV + GitHub alerts | ✅ GitHub alerts | ❌ |\n| Dependency Dashboard (single overview issue) | ✅ | ❌ | ❌ |\n| Schedule / batching | ✅ | ⚠️ basic | ⚠️ via cron workflow |\n| Self-hostable (no third-party app) | ✅ (official Action) | ✅ (GitHub-native) | ✅ (CLI) |\n| Config surface | medium | low | minimal |\n| Cost for open source | free | free | free |\n\n### Verdict\n\n- **Renovate — recommended.** It is the only option that models KoliBri's reality in _one_ config:\n group the Angular/React/Stencil families, hold each adapter folder on its pinned major, automerge\n the safe stuff (GitHub Actions, `@types/*`), and route everything risky to a review queue (the\n Dependency Dashboard). It also folds in what we currently split across **two** systems\n (Dependabot for Actions + a daily `ncu` workflow for npm).\n- **Dependabot — viable fallback.** Now supports `groups:`, but every package directory needs its\n own `updates:` entry (≈30 for this monorepo × 4 branches) and it cannot hold a dependency on a\n specific major _per folder_ — exactly what the `angular/v19|v20|v21` and `react*` adapters need.\n- **npm-check-updates — not an automation tool.** It is a CLI that rewrites version ranges; it has\n no PR/grouping/scheduling of its own. We only use it _inside_ a hand-written workflow\n (`.github/workflows/auto-dependency-updater.yml`). Renovate makes that workflow redundant.\n\n---\n\n## 2. What the exemplary `renovate.json` does\n\nThe committed [`renovate.json`](../renovate.json) is tailored to this repo. Highlights:\n\n### Global behaviour\n\n- **`extends: [\"config:recommended\", \"security:openssf-scorecard\"]`** — sensible defaults plus\n OpenSSF Scorecard badges on PRs.\n- **Conventional Commits** — `chore(deps): …` titles so PRs pass `pr-title-validation.yml`.\n- **`labels: [\"dependencies\", \"renovate\", \"release:engineering\"]`** — the `release:*` label is\n **required** by `pr-release-label-validation.yml`; `release:engineering` files dependency PRs\n under _🔧 Engineering_ in the changelog (see `.github/release.yml`).\n- **Weekly schedule** (`before 6am on monday`, `Europe/Berlin`) with `prConcurrentLimit: 10` /\n `prHourlyLimit: 4` so the first run does **not** flood the repo with PRs.\n- **`baseBranchPatterns`** — runs on `develop` **and** `release/3|2|1`; the maintenance branches are\n restricted to security + patch npm updates so released majors stay stable.\n- **`lockFileMaintenance`** — weekly `pnpm-lock.yaml` refresh (replaces the manual\n `04 - Update pnpm Lock` workflow runs).\n- **`postUpdateOptions: [\"pnpmDedupe\"]`** — keeps the pnpm lockfile tidy.\n\n### Grouping & guard-rails (the important part for this monorepo)\n\n| Rule | Effect |\n| ------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| **All majors** | Require manual approval via the Dependency Dashboard — KoliBri pins majors deliberately. |\n| **Angular `@angular/*`, `zone.js`, `ng-packagr`** | Major updates **disabled** entirely; within-major updates grouped per adapter folder (_Angular 19/20/21_). A new Angular major = a new adapter folder, never an auto-bump. |\n| **React `react`, `react-dom`, `@types/react*`** | Major updates **disabled**; within-major React updates of the `react*` adapters grouped and reviewed (not automerged). |\n| **Stencil `@stencil/*`, `@stencil-community/*`** | **All** updates require dashboard approval — every 4.39+ release currently breaks the Popover API, tooltips and visual tests (see [`UPGRADEABLE_DEPENDENCIES.md`](./UPGRADEABLE_DEPENDENCIES.md)). |\n| **`@kern-ux/*`** | Dashboard approval only — upgraded by hand together with theming work. |\n| **`@typescript-eslint/*`, ESLint core + plugins** | Minor/major require approval (9 → 10 is a breaking migration). |\n| **`jest*`, `typescript`** | Majors/non-patch require approval. |\n| **`github-actions`, `@types/*`** | Grouped **and automerged** for low-risk update types. |\n| **Stylelint, Playwright** | Grouped into single PRs. |\n\n> The pins above mirror exactly what the current `ncu:*` scripts exclude\n> (`@kern-ux/*`, `@stencil/*`, `@typescript-eslint/*`) and what `UPGRADEABLE_DEPENDENCIES.md`\n> documents as breaking — so behaviour is preserved, just expressed declaratively.\n\n### Validate the config locally\n\n```sh\nnpx --yes --package renovate renovate-config-validator renovate.json\n```\n\n---\n\n## 3. Enabling Renovate\n\nTwo ways to run it; **this repo is wired for Option A**.\n\n### Option A — Self-hosted via GitHub Actions (committed in this repo)\n\nThis repo ships [`.github/workflows/renovate.yml`](../.github/workflows/renovate.yml). It runs Renovate\non a weekly schedule (Mondays 04:00 UTC) **and** on demand via the **Run workflow** button\n(`workflow_dispatch`, with an optional `dry_run` preview). It authenticates through the existing GitHub\nApp (`APP_ID` / `PRIVATE_KEY` secrets, shared with _04 - Update pnpm Lock_).\n\nTo activate it:\n\n1. Ensure that GitHub App installation grants **contents: write**, **pull-requests: write**,\n **issues: write** (for the Dependency Dashboard) and **workflows: write** (so the `github-actions`\n manager may update `.github/workflows/*`). _Alternative:_ replace the app-token step with a\n `RENOVATE_TOKEN` PAT/fine-grained token carrying the same scopes.\n2. Trigger the workflow once via **Run workflow** (optionally with `dry_run` enabled) to verify it, then\n let the weekly schedule take over.\n\n> **Tip:** The `dry_run` input maps to `RENOVATE_DRY_RUN=full`, so the first manual run previews every PR\n> Renovate _would_ open without creating anything.\n\n### Option B — Mend-hosted GitHub App (alternative, zero maintenance)\n\nIf you would rather not self-host, delete `.github/workflows/renovate.yml` and instead:\n\n1. Have an **org admin** install the [Renovate GitHub App](https://github.com/apps/renovate) on\n `public-ui` (or just on `public-ui/kolibri`).\n2. Renovate detects `renovate.json` and opens a Dependency Dashboard issue.\n3. Review the dashboard, then let it run on the weekly schedule.\n\n---\n\n## 4. Migration checklist (do this only after Renovate is verified)\n\nOnce Renovate runs green for a cycle, retire the overlapping automation to avoid **duplicate PRs**:\n\n- [ ] Remove `.github/dependabot.yml` (Renovate now manages GitHub Actions — see the\n `github-actions` group).\n- [ ] Remove `.github/workflows/auto-dependency-updater.yml` (the daily `ncu` PR job).\n- [ ] Drop the `ncu:*` / `update` scripts and the `npm-check-updates` devDependency from the root\n `package.json`, plus `.ncurc.json` (optional — `ncu` is still handy for manual ad-hoc checks).\n- [ ] Keep `04 - Update pnpm Lock` if you still want a manual lockfile-refresh button; otherwise\n Renovate's `lockFileMaintenance` covers it.\n\nUntil every box is ticked, **leave the existing tooling in place** — Renovate only acts once the\nworkflow (or app) from [§3](#3-enabling-renovate) actually runs, so there is no conflict in the meantime.\n\n---\n\n## 🇩🇪 Zusammenfassung\n\n**Empfehlung: Renovate.** Es ist die einzige Lösung, die das KoliBri-Monorepo in _einer_ Konfiguration\nabbildet — verwandte Pakete gruppieren (z. B. alle `@angular/*`), jeden Adapter-Ordner auf seiner\nfixierten Major-Version halten (`angular/v19|v20|v21`, `react*`), sichere Updates automatisch mergen\n(GitHub Actions, `@types/*`) und alles Riskante (Stencil, kern-ux, ESLint-/Angular-Majors) über das\n**Dependency Dashboard** zur manuellen Freigabe leiten.\n\n- **Dependabot** kann zwar gruppieren, braucht aber pro Paketverzeichnis einen eigenen Eintrag\n (≈30 × 4 Branches) und kann ein Paket nicht _pro Ordner_ auf einer Major-Version halten.\n- **npm-check-updates** ist nur ein CLI ohne eigene Automatisierung (läuft heute im Workflow\n `auto-dependency-updater.yml`).\n\nDie fertige [`renovate.json`](../renovate.json) liegt im Repo-Root (geprüft mit dem offiziellen\n`renovate-config-validator`), und der self-hosted Runner-Workflow\n[`.github/workflows/renovate.yml`](../.github/workflows/renovate.yml) ist ebenfalls committet.\n**Renovate läuft**, sobald der Workflow startet — wöchentlich per Zeitplan oder manuell über den\n**Run workflow**-Button (Option A); alternativ kann ein Org-Admin die\n[Renovate-GitHub-App](https://github.com/apps/renovate) installieren (Option B). Bis dahin bleibt die\nbestehende Dependabot-/ncu-Automatisierung zuständig; danach greift die Migrations-Checkliste oben.\n",
|
|
456
|
+
"code": "# Renovate — Automated Dependency Updates\n\nThis document is the outcome of issue [#10270](https://github.com/public-ui/kolibri/issues/10270)\n(_renovate vs npm-check-updates vs dependabot_). It contains:\n\n1. a comparison of the three candidate tools,\n2. a description of the exemplary [`renovate.json`](../renovate.json) that ships with this repo,\n3. how to enable Renovate, and\n4. the migration checklist for retiring the current tooling.\n\n> **Status:** The `renovate.json` and a self-hosted runner workflow\n> ([`.github/workflows/renovate.yml`](../.github/workflows/renovate.yml)) are committed as an\n> **exemplary, ready-to-run setup**. Renovate stays **idle** until that workflow runs — either on its\n> every-4-hours schedule or via the manual **Run workflow** button (see [Enabling Renovate](#enabling-renovate)).\n> Until then the existing Dependabot + npm-check-updates automation stays in charge.\n\n---\n\n## 1. Tool comparison\n\nKoliBri is a **pnpm-workspace monorepo** with 30+ packages, several intentionally pinned major\nlines (Angular `v19`/`v20`/`v21`, React 18/19, Stencil 4, ESLint 9) and four maintained branches\n(`develop`, `release/3`, `release/2`, `release/1`). That shapes the comparison:\n\n| Capability | **Renovate** | Dependabot | npm-check-updates (ncu) |\n| -------------------------------------------- | :----------------------: | :---------------------------------: | :-----------------------: |\n| pnpm-workspace aware | ✅ native | ⚠️ partial | ❌ manual (per-package) |\n| One PR grouping related packages | ✅ fully configurable | ⚠️ `groups:` only | ❌ none |\n| Hold a package on a specific major line | ✅ per-folder rules | ⚠️ `ignore` (global) | ⚠️ `-x` exclude (global) |\n| GitHub Actions updates | ✅ | ✅ | ❌ |\n| Lockfile-only refresh | ✅ `lockFileMaintenance` | ⚠️ limited | ❌ (needs `pnpm install`) |\n| Automerge (per update type) | ✅ | ⚠️ limited | ❌ |\n| Multi-base-branch (release/\\*) support | ✅ `baseBranchPatterns` | ✅ `target-branch` (one entry each) | ⚠️ matrix in a workflow |\n| Security / vulnerability remediation | ✅ OSV + GitHub alerts | ✅ GitHub alerts | ❌ |\n| Dependency Dashboard (single overview issue) | ✅ | ❌ | ❌ |\n| Schedule / batching | ✅ | ⚠️ basic | ⚠️ via cron workflow |\n| Self-hostable (no third-party app) | ✅ (official Action) | ✅ (GitHub-native) | ✅ (CLI) |\n| Config surface | medium | low | minimal |\n| Cost for open source | free | free | free |\n\n### Verdict\n\n- **Renovate — recommended.** It is the only option that models KoliBri's reality in _one_ config:\n group the Angular/React/Stencil families, hold each adapter folder on its pinned major, automerge\n the safe stuff (GitHub Actions, `@types/*`), and route everything risky to a review queue (the\n Dependency Dashboard). It also folds in what we currently split across **two** systems\n (Dependabot for Actions + a daily `ncu` workflow for npm).\n- **Dependabot — viable fallback.** Now supports `groups:`, but every package directory needs its\n own `updates:` entry (≈30 for this monorepo × 4 branches) and it cannot hold a dependency on a\n specific major _per folder_ — exactly what the `angular/v19|v20|v21` and `react*` adapters need.\n- **npm-check-updates — not an automation tool.** It is a CLI that rewrites version ranges; it has\n no PR/grouping/scheduling of its own. We only use it _inside_ a hand-written workflow\n (`.github/workflows/auto-dependency-updater.yml`). Renovate makes that workflow redundant.\n\n---\n\n## 2. What the exemplary `renovate.json` does\n\nThe committed [`renovate.json`](../renovate.json) is tailored to this repo. Highlights:\n\n### Global behaviour\n\n- **`extends: [\"config:recommended\", \"security:openssf-scorecard\"]`** — sensible defaults plus\n OpenSSF Scorecard badges on PRs.\n- **Conventional Commits** — `chore(deps): …` titles so PRs pass `pr-title-validation.yml`.\n- **`labels: [\"dependencies\", \"renovate\", \"release:engineering\"]`** — the `release:*` label is\n **required** by `pr-release-label-validation.yml`; `release:engineering` files dependency PRs\n under _🔧 Engineering_ in the changelog (see `.github/release.yml`).\n- **Every-4-hours cadence** — the workflow cron runs Renovate every 4 hours; `renovate.json` itself\n allows PR creation `at any time`, so the workflow schedule governs. `prConcurrentLimit: 5` /\n `prHourlyLimit: 5` cap the number of open PRs **per base branch** (so `develop` and each\n `release/*` branch have their own budget).\n- **`minimumReleaseAge: \"3 days\"`** — all updates (npm, Actions, …, including security fixes)\n are held back for three days after release before a PR is opened or auto-merged. This protects\n against compromised or quickly-revoked releases.\n- **Automerge all non-major updates (squash)** — the first package rule enables `automerge` for\n `patch`/`minor`/`digest`/`pin`/lockfile updates; `automergeStrategy: squash` means each\n dependency bump becomes a single commit. Known-risky rules below (Stencil, kern-ux, ESLint,\n TypeScript, typescript-eslint) override it back to manual. Majors always keep dashboard approval.\n Prerequisites: repo setting **Allow auto-merge** enabled, green pipelines enforced via required\n status checks on `develop`, and the runner GitHub App listed in the branch-protection bypass\n (see [Enabling Renovate](#enabling-renovate)).\n- **`baseBranchPatterns`** — runs on `develop` **and** `release/3|2|1`; the maintenance branches are\n **security-only** (all regular npm and GitHub Actions updates are disabled) so released majors stay\n stable. Security PRs still automerge when non-major; major security updates require dashboard\n approval.\n- **`lockFileMaintenance`** — weekly `pnpm-lock.yaml` refresh (replaces the manual\n `04 - Update pnpm Lock` workflow runs).\n- **`configMigration: true`** — Renovate keeps `renovate.json` itself up to date when built-in\n presets or options change.\n- **`dependencyDashboardOSVVulnerabilitySummary: \"all\"`** — adds an OSV vulnerability table\n directly to the Dependency Dashboard issue.\n- **`postUpdateOptions: [\"pnpmDedupe\"]`** — keeps the pnpm lockfile tidy.\n\n### Grouping & guard-rails (the important part for this monorepo)\n\n| Rule | Effect |\n| ------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| **All majors** | Require manual approval via the Dependency Dashboard — KoliBri pins majors deliberately. |\n| **Angular `@angular/*`, `zone.js`, `ng-packagr`** | Major updates **disabled** entirely; within-major updates grouped per adapter folder (_Angular 19/20/21_). A new Angular major = a new adapter folder, never an auto-bump. |\n| **React `react`, `react-dom`, `@types/react*`** | Major updates **disabled**; within-major React updates of the `react*` adapters grouped and automerged once green. |\n| **Stencil `@stencil/*`, `@stencil-community/*`** | **All** updates require dashboard approval — every 4.39+ release currently breaks the Popover API, tooltips and visual tests (see [`UPGRADEABLE_DEPENDENCIES.md`](./UPGRADEABLE_DEPENDENCIES.md)). |\n| **`@kern-ux/*`** | Dashboard approval only — upgraded by hand together with theming work. |\n| **`@typescript-eslint/*`, ESLint core + plugins** | Minor/major require approval (9 → 10 is a breaking migration). |\n| **`jest*`, `typescript`** | Majors/non-patch require approval. |\n| **`github-actions`, `@types/*`** | Grouped; automerged like every other non-major update. |\n| **Stylelint, Playwright** | Grouped into single PRs. |\n\n> The pins above mirror exactly what the current `ncu:*` scripts exclude\n> (`@kern-ux/*`, `@stencil/*`, `@typescript-eslint/*`) and what `UPGRADEABLE_DEPENDENCIES.md`\n> documents as breaking — so behaviour is preserved, just expressed declaratively.\n\n### Validate the config locally\n\n```sh\nnpx --yes --package renovate renovate-config-validator renovate.json\n```\n\n---\n\n## 3. Enabling Renovate\n\nTwo ways to run it; **this repo is wired for Option A**.\n\n### Option A — Self-hosted via GitHub Actions (committed in this repo)\n\nThis repo ships [`.github/workflows/renovate.yml`](../.github/workflows/renovate.yml). It runs Renovate\n**every 4 hours** (`0 */4 * * *` UTC) **and** on demand via the **Run workflow** button\n(`workflow_dispatch`, with an optional `dry_run` preview). It authenticates through the existing GitHub\nApp (`APP_ID` / `PRIVATE_KEY` secrets, shared with _04 - Update pnpm Lock_).\n\nTo activate it:\n\n1. Ensure that GitHub App installation grants **contents: write**, **pull-requests: write**,\n **issues: write** (for the Dependency Dashboard) and **workflows: write** (so the `github-actions`\n manager may update `.github/workflows/*`). _Alternative:_ replace the app-token step with a\n `RENOVATE_TOKEN` PAT/fine-grained token carrying the same scopes.\n2. For automerge to work end to end, check three repository settings:\n - **Settings → General → Pull Requests → Allow auto-merge**: enabled (Renovate uses\n `platformAutomerge`, i.e. GitHub's native auto-merge).\n - **Branch protection for `develop` (and `release/2`, `release/1`, `release/3`) → required status\n checks**: add the CI gate jobs (`check-results`, `validate-pr-title`) so a PR is only merged\n when the pipelines are green.\n - **Branch protection for `develop` (and `release/*`) → bypass pull request allowances**: the\n runner App (`publicuibot`) must be listed there, so its PRs can merge without a human\n code-owner review.\n3. Trigger the workflow once via **Run workflow** (optionally with `dry_run` enabled) to verify it, then\n let the 4-hours schedule take over.\n\n> **Tip:** The `dry_run` input maps to `RENOVATE_DRY_RUN=full`, so the first manual run previews every PR\n> Renovate _would_ open without creating anything.\n\n### Option B — Mend-hosted GitHub App (alternative, zero maintenance)\n\nIf you would rather not self-host, delete `.github/workflows/renovate.yml` and instead:\n\n1. Have an **org admin** install the [Renovate GitHub App](https://github.com/apps/renovate) on\n `public-ui` (or just on `public-ui/kolibri`).\n2. Renovate detects `renovate.json` and opens a Dependency Dashboard issue.\n3. Review the dashboard, then let it run on the weekly schedule.\n\n---\n\n## 4. Migration checklist (do this only after Renovate is verified)\n\nOnce Renovate runs green for a cycle, retire the overlapping automation to avoid **duplicate PRs**.\nStatus as of the Renovate activation for `develop`:\n\n- [x] Removed `.github/dependabot.yml` (Renovate now manages GitHub Actions — see the\n `github-actions` group).\n- [x] Removed `.github/workflows/auto-dependency-updater.yml` (the daily `ncu` PR job).\n- [x] Dropped the `ncu:*` / `update` scripts and the `npm-check-updates` devDependency from the root\n `package.json`, plus `.ncurc.json`.\n- [ ] Keep `04 - Update pnpm Lock` if you still want a manual lockfile-refresh button; otherwise\n Renovate's `lockFileMaintenance` covers it.\n\nUntil every box is ticked, **leave the existing tooling in place** — Renovate only acts once the\nworkflow (or app) from [§3](#3-enabling-renovate) actually runs, so there is no conflict in the meantime.\n\n---\n\n## 🇩🇪 Zusammenfassung\n\n**Empfehlung: Renovate.** Es ist die einzige Lösung, die das KoliBri-Monorepo in _einer_ Konfiguration\nabbildet — verwandte Pakete gruppieren (z. B. alle `@angular/*`), jeden Adapter-Ordner auf seiner\nfixierten Major-Version halten (`angular/v19|v20|v21`, `react*`), sichere Updates automatisch mergen\n(GitHub Actions, `@types/*`) und alles Riskante (Stencil, kern-ux, ESLint-/Angular-Majors) über das\n**Dependency Dashboard** zur manuellen Freigabe leiten.\n\n- **Dependabot** kann zwar gruppieren, braucht aber pro Paketverzeichnis einen eigenen Eintrag\n (≈30 × 4 Branches) und kann ein Paket nicht _pro Ordner_ auf einer Major-Version halten.\n- **npm-check-updates** ist nur ein CLI ohne eigene Automatisierung (läuft heute im Workflow\n `auto-dependency-updater.yml`).\n\nNeu hinzugekommen: `minimumReleaseAge: \"3 Tage\"` schützt vor kompromittierten Releases\n(inklusive Security-Updates), `automergeStrategy: squash` sorgt für saubere Commit-Historie,\nund die `release/*`-Branches werden auf **Security-only** umgestellt — reguläre npm- und\nGitHub-Actions-Updates werden dort komplett deaktiviert, während Vulnerability-Alert-PRs\nweiterhin (bei Nicht-Major) automatisch mergen.\n\nDie fertige [`renovate.json`](../renovate.json) liegt im Repo-Root (geprüft mit dem offiziellen\n`renovate-config-validator`), und der self-hosted Runner-Workflow\n[`.github/workflows/renovate.yml`](../.github/workflows/renovate.yml) ist ebenfalls committet.\n**Renovate läuft**, sobald der Workflow startet — alle 4 Stunden per Zeitplan oder manuell über den\n**Run workflow**-Button (Option A); alternativ kann ein Org-Admin die\n[Renovate-GitHub-App](https://github.com/apps/renovate) installieren (Option B). Bis dahin bleibt die\nbestehende Dependabot-/ncu-Automatisierung zuständig; danach greift die Migrations-Checkliste oben.\n",
|
|
457
457
|
"kind": "doc"
|
|
458
458
|
},
|
|
459
459
|
{
|
|
@@ -504,6 +504,14 @@
|
|
|
504
504
|
"code": "# Upgradeable Dependencies — Major Versions Available\n\n**Analysis Date:** 2026-03-31 \n**Scope:** Root package.json + all packages in `packages/*/` \n**Method:** npm-check-updates with `--target greatest`\n\n---\n\n## 🔴 Critical (Breaking Changes – Manual Work Required)\n\n### 1. **@stencil/core** | 4.38.3 (pinned) → 4.43.5 (patch, BLOCKED) / 5.0.0-alpha.7 (major)\n\n- **Status:** ⚠️ Pinned to 4.38.3 — every newer 4.x release changes runtime behavior\n (verified 2026-06-11 by E2E A/B bisect on this codebase):\n - 4.39.0 / 4.40.0: build fails (SCSS parse error in input-date; fixed in 4.40.1)\n - 4.40.1: tooltip no longer hides when a popover opens\n (popover-button.e2e.ts:41 fails consistently); CI visual tests fail across all\n themes; hydrate output differs (e.g. kol-input-file browse button renders\n `kol-button--normal` → behavior drift in SSR output)\n - 4.41.0 – 4.43.5: native Popover API broken — `showPopover()` elements stay\n hidden (kol-popover, kol-popover-button, kol-split-button, table settings)\n- **Breaking Changes (v5):**\n - v5.0.0-alpha.7 is not production-ready (alpha channel)\n - Multiple output-target packages block v5 upgrade:\n - @public-ui/stencil-angular-output-target\n - @public-ui/stencil-react-output-target\n - @public-ui/stencil-solid-output-target\n - @public-ui/stencil-vue-output-target\n - @stencil/playwright requires >=4.13.0, conflicts with 5.x\n- **Risk:** VERY HIGH – Core platform dependency\n- **Recommendation:** Stay on 4.38.3; before any future bump, run the popover/tooltip\n E2E suites and the visual tests against the candidate version\n- **Effort:** Would require coordinating 4+ downstream packages plus resolving the\n popover/tooltip regressions (upstream fix or component-side adaptation)\n\n### 2. **eslint** | 9.39.4 → 10.1.0\n\n- **Breaking Changes:**\n - Legacy `.eslintrc.json` configuration is no longer supported; must migrate to flat config (`eslint.config.js`)\n - Node.js < v20.19.0 no longer supported\n - Config file lookup now starts from linted file's directory (beneficial for monorepos)\n - Formatter output depends on Node.js native `styleText()` API\n - NO_COLOR and NODE_DISABLE_COLORS environment variables now affect color output\n - FlatESLint and LegacyESLint deprecated APIs removed\n - JSX reference tracking improved (may affect scope-dependent rules)\n- **Peer Dependencies:** Requires @eslint/js ^10.0.0 and eslint-plugin-jsx-a11y compatibility\n- **Config Changes:** Must convert `.eslintrc.json` to `eslint.config.js` (tool available: `eslint --init`)\n- **Risk:** HIGH – Affects all linting configuration\n- **Effort:** MEDIUM – Config migration required but automation tools available\n- **Roadmap:** [Migrate to v10.x](https://eslint.org/docs/latest/use/migrate-to-10.0.0)\n\n### 3. **jest** | 26.6.3 → 30.3.0\n\n- **Breaking Changes:**\n - Node.js 14, 16, 19, 21 no longer supported (require >=18.x, >=20.x)\n - Minimum TypeScript now 5.4+\n - jest-environment-jsdom upgraded from jsdom 21 → jsdom 26 (spec compliance changes)\n - Mocking `window.location` behavior may change\n - Deprecated alias methods removed (e.g., `toBeTruthy()` aliases)\n - Non-enumerable object properties excluded from matchers by default\n - `jest.mock()` now case-sensitive (affects Windows edge cases)\n - `jest.genMockFromModule()` removed (use `jest.createMockFromModule()`)\n - `--testPathPattern` renamed to `--testPathPatterns`\n - Performance: Real-world speedups from optimizations\n- **Risk:** HIGH – Core testing framework with wide breaking surface\n- **Effort:** MEDIUM → HIGH – Will require test review and fixes\n- **Migration:** [Jest 30 Migration Guide](https://jestjs.io/docs/upgrading-to-jest30)\n\n### 4. **TypeScript** | 5.9.3 → 6.0.2\n\n- **Breaking Changes:**\n - `moduleResolution: classic` removed (only nodenext, bundler supported)\n - AMD, UMD, SystemJS modules removed (ESM only)\n - `esModuleInterop` and `allowSyntheticDefaultImports` cannot be set to false\n - `target: es5` deprecated; minimum ES2015\n - All code treated as strict mode (automatic \"use strict\" emission)\n- **Config Migration:** Migration CLI available: `npx @andrewbranch/ts5to6`\n- **Impact:** May be low if tsconfig.json is explicit and uses modern settings\n- **Peer:** @stencil-community/eslint-plugin requires ^4.9.4 || ^5.0.0 (blocks 6.0+)\n- **Risk:** MEDIUM – Language compiler fundamental shift\n- **Effort:** LOW → MEDIUM – Config migration mostly automatic\n- **Roadmap:** [TypeScript 5.x to 6.0 Migration Guide](https://gist.github.com/privatenumber/3d2e80da28f84ee30b77d53e1693378f)\n\n### 5. **@angular/core** | 19.2.20 → 22.0.0-next.5 (Angular v19, v20, v21 adapters)\n\n- **Packages Affected:**\n - `/packages/adapters/angular/v19/`: 19.2.20 → 22.0.0-next.5\n - `/packages/adapters/angular/v20/`: 20.3.18 → 22.0.0-next.5\n - `/packages/adapters/angular/v21/`: 21.2.6 → 22.0.0-next.5\n- **Breaking Changes (v20+):**\n - Node.js >=22.22.0 required (v24.13.1+) – v20 no longer supported\n - TypeScript >=5.8 required\n - Zoneless applications now stable (Zone.js side effects deprecated)\n - Ivy strict mode enabled by default\n - ViewEngine completely removed\n - NgModules support deprecated in favor of standalone components\n- **Complexity:** Enterprise applications can take weeks to migrate\n- **Related:** Also affects @angular/compiler, @angular/compiler-cli, zone.js, @angular/common\n- **Risk:** VERY HIGH – Multi-framework adapter dependencies\n- **Effort:** HIGH – Complete architectural review needed\n- **Roadmap:** [Angular Update Guide](https://angular.dev/update-guide)\n\n---\n\n## 🟡 High (Test-Intensive Upgrades)\n\n### 1. **jest** (component package) | 26.6.3 → 30.3.0\n\n- **Location:** `/packages/components/`\n- **Risk:** Same as critical jest (see above), but scoped to component tests\n- **Effort:** MEDIUM\n- **Testing:** All component unit tests must run and pass\n\n### 2. **@types/jest** | 26.0.24 → 30.0.0\n\n- **Breaking:** TypeScript types for jest@30 (follows jest breaking changes)\n- **Dependency:** Must upgrade together with jest\n- **Risk:** MEDIUM\n- **Effort:** LOW – Automatic with jest upgrade\n\n### 3. **knip** | 5.88.1 → 6.1.0 (components, stylelint-rules)\n\n- **Breaking Changes:**\n - Node.js <v20.19.0 no longer supported\n - Issue type `classMembers` removed\n - `--include-libs` and `--isolate-workspaces` flags removed (now default)\n - `--experimental-tags` renamed to `--tags`\n - `issues.files` structure changes in reporters\n - `issues._files` removed\n - Root files removed\n- **Packages:** tools/stylelint-rules, components\n- **Risk:** MEDIUM – Unused-code detection configuration changes\n- **Effort:** LOW → MEDIUM – Config review needed\n- **Roadmap:** [knip v6 Releases](https://github.com/webpro-nl/knip/releases)\n\n### 4. **@types/color-convert** | 2.0.4 → 3.0.1 + **color-rgba** | 2.4.0 → 3.0.0\n\n- **Location:** `/packages/components/`\n- **Breaking Changes:** Major version bump on color-rgba (internal API changes likely)\n- **Risk:** MEDIUM – Type definitions and color processing\n- **Effort:** LOW – Likely compatible\n- **Notes:** These are typically non-breaking for consumers\n\n### 5. **@typescript-eslint/eslint-plugin** & **@typescript-eslint/parser** | 8.57.2 → 8.58.0 (patch)\n\n- **Note:** ncu shows 8.58.1-alpha.0 as \"greatest\" but 8.58.0 is stable latest\n- **Peer:** @stencil-community/eslint-plugin requires ^7.0.0 || ^8.0.0\n- **Risk:** LOW\n- **Effort:** LOW – Patch upgrade\n\n### 6. **cssnano** | 7.1.3 → 7.1.4\n\n- **Risk:** LOW – Patch-level CSS minifier\n- **Effort:** LOW\n\n### 7. **postcss-sorting** | 9.1.0 → 10.0.0\n\n- **Location:** `/packages/components/`\n- **Breaking Changes:** Likely minor API changes (changelog not specific in v9→v10)\n- **Risk:** MEDIUM – CSS property ordering configuration\n- **Effort:** LOW → MEDIUM\n- **Roadmap:** [postcss-sorting CHANGELOG](https://github.com/hudochenkov/postcss-sorting/blob/master/CHANGELOG.md)\n\n### 8. **mocha** | 11.7.5 → 12.0.0-beta-9\n\n- **Status:** Beta release only\n- **Breaking:** Likely breaking changes in beta\n- **Risk:** MEDIUM\n- **Effort:** MEDIUM – Wait for stable v12.0.0 release\n- **Recommendation:** Defer until stable release\n\n### 9. **cpy-cli** | 6.0.0 → 7.0.0 (themes package)\n\n- **Breaking:** Major file copy utility version\n- **Risk:** MEDIUM – Copy script behavior changes likely\n- **Effort:** LOW → MEDIUM\n- **Testing:** Verify theme build output\n\n---\n\n## 🟢 Low (Safe Upgrades)\n\n### 1. **@eslint/js** | 9.39.4 → 10.0.1 (themes, stylelint-rules, components)\n\n- **Peer Dependency:** Requires eslint ^10.0.0 (blocks eslint upgrade dependency)\n- **Risk:** LOW – Language rule sets\n- **Effort:** LOW\n- **Upgrade Path:** Do together with eslint v10.0.0\n\n### 2. **minimatch** | 10.2.4 → 10.2.5 (React, Vue, Svelte, Angular v19/v20/v21)\n\n- **Type:** Patch-level glob matching utility\n- **Risk:** VERY LOW\n- **Effort:** TRIVIAL\n\n### 3. **rollup** | 4.60.0 → 4.60.1 (themes)\n\n- **Type:** Patch-level bundler\n- **Risk:** VERY LOW\n- **Effort:** TRIVIAL\n\n### 4. **npm-run-all2** | 8.0.4 → 8.1.0-beta.0 (root)\n\n- **Note:** Beta version only\n- **Risk:** LOW (beta)\n- **Recommendation:** Wait for stable 8.1.0\n\n### 5. **stylelint-order** | 7.0.1 → 8.1.1 (root)\n\n- **Type:** CSS plugin\n- **Risk:** LOW – Property ordering\n- **Effort:** LOW\n\n### 6. **svelte** | ^5.55.0 → ^5.55.1 (svelte adapter)\n\n- **Type:** Patch-level framework\n- **Risk:** VERY LOW\n- **Effort:** TRIVIAL\n\n### 7. **@babel/types** | 7.29.0 → 8.0.0-rc.3 (Vue, Svelte adapters)\n\n- **Status:** Release candidate\n- **Risk:** MEDIUM (RC stage)\n- **Effort:** LOW\n- **Recommendation:** Wait for stable 8.0.0 release\n\n### 8. **zone.js** | 0.15.1 → 0.16.1 (Angular adapters v19-v21)\n\n- **Type:** Angular zone management\n- **Dependency:** Follows Angular major versions\n- **Risk:** LOW (if upgrading Angular)\n- **Effort:** LOW\n\n---\n\n## Summary\n\n### Upgrade Statistics\n\n| Category | Count | Total Packages Affected |\n| --------------------------------- | ------- | ---------------------------- |\n| 🔴 Critical | 5 | 9 packages (with variations) |\n| 🟡 High | 9 | 7 unique packages |\n| 🟢 Low | 8 | 15 unique packages |\n| **Total Unique Upgradeable Deps** | **~22** | **Across entire monorepo** |\n\n### Critical Blockers & Interdependencies\n\n```\n1. @stencil/core@5 BLOCKED by:\n - @public-ui/stencil-angular-output-target (requires >=4)\n - @public-ui/stencil-react-output-target (requires >=4)\n - @public-ui/stencil-solid-output-target (requires >=2.17.2)\n - @public-ui/stencil-vue-output-target (requires >=4)\n - @stencil/playwright (requires >=4.13.0)\n ACTION: Keep on 4.38.3 — 4.39+ regresses popover/tooltip behavior (see Critical #1);\n v5 additionally blocked until output-targets are v5-compatible\n\n2. eslint@10.0.0 blocks:\n - @stencil-community/eslint-plugin (requires ^8.0.0 || ^9.0.0)\n - eslint-plugin-jsx-a11y (requires ^8.0.0 || ^9.0.0)\n ACTION: Coordinate multi-package eslint migration\n\n3. prettier@3.8.1 blocked by:\n - prettier-plugin-organize-imports (requires >=2.0)\n ACTION: prettier@4.0.0-alpha.13 incompatible; stay on v3\n\n4. TypeScript@6.0.2 blocked by:\n - @stencil-community/eslint-plugin (requires ^4.9.4 || ^5.0.0)\n ACTION: Stay on TypeScript 5.x for now\n\n5. Angular@22 (next.5) not stable:\n - v20: Angular-specific adapters only\n - Migration complex: weeks for enterprise apps\n ACTION: Keep Angular adapters on current major versions\n```\n\n### Recommended Upgrade Priority\n\n#### Phase 1 (Immediate – Low Risk)\n\n- ✅ minimatch (10.2.4 → 10.2.5) — patch only\n- ✅ rollup (4.60.0 → 4.60.1) — patch only\n- ✅ stylelint-order (7.0.1 → 8.1.1) — CSS plugin\n- ✅ cssnano (7.1.3 → 7.1.4) — patch only\n\n#### Phase 2 (Short-term – High Effort)\n\n- ⚠️ jest@30 + @types/jest@30 — test suite migration (2-5 days)\n - Scoped start: `/packages/components/` component tests\n - Follow with root/adapters test suites\n- ⚠️ eslint@10 + @eslint/js@10 — config migration (1-3 days)\n - Convert `.eslintrc.json` → `eslint.config.js`\n - Test all lint rules\n - Update CI/CD pipelines\n\n#### Phase 3 (Medium-term – Coordinate)\n\n- ⚠️ TypeScript@6 — only after reviewing @stencil-community/eslint-plugin compatibility\n- ⚠️ knip@6 — unused-code detection, config review (0.5-1 day)\n\n#### Phase 4 (Blocked – Wait for Stable)\n\n- ❌ prettier@4.0.0-alpha → keep v3 until stable (blocked by prettier-plugin-organize-imports)\n- ❌ @stencil/core@5 → wait for output-target compatibility\n- ❌ Angular@22 → stay on v19/v20/v21 adapter versions (production-critical)\n- ❌ mocha@12, @babel/types@8 → wait for stable releases (beta only)\n\n### Estimated Overall Effort\n\n| Phase | Effort | Timeline | Risk |\n| -------------------------- | ------------- | ------------- | ----------- |\n| Phase 1 | LOW | 0.5-1 hour | VERY LOW |\n| Phase 2 | HIGH | 3-5 days | MEDIUM-HIGH |\n| Phase 3 | MEDIUM | 1-2 days | MEDIUM |\n| Phase 4 | BLOCKED | N/A | BLOCKED |\n| **Total (if all applied)** | **VERY HIGH** | **2-3 weeks** | **HIGH** |\n\n---\n\n## Research Sources\n\n- [Migrate to ESLint v10.x](https://eslint.org/docs/latest/use/migrate-to-10.0.0)\n- [Jest 30 Migration Guide](https://jestjs.io/docs/upgrading-to-jest30)\n- [TypeScript 5.x to 6.0 Migration Guide](https://gist.github.com/privatenumber/3d2e80da28f84ee30b77d53e1693378f)\n- [Angular Update Guide](https://angular.dev/update-guide)\n- [Knip v6 Releases](https://github.com/webpro-nl/knip/releases)\n- [Stencil Releases](https://github.com/ionic-team/stencil/releases)\n- [postcss-sorting CHANGELOG](https://github.com/hudochenkov/postcss-sorting/blob/master/CHANGELOG.md)\n",
|
|
505
505
|
"kind": "doc"
|
|
506
506
|
},
|
|
507
|
+
{
|
|
508
|
+
"id": "doc/visual-review",
|
|
509
|
+
"group": "docs",
|
|
510
|
+
"name": "visual-review",
|
|
511
|
+
"path": "docs/visual-review.md",
|
|
512
|
+
"code": "# Visual Review\n\nHow screenshot changes of the KoliBri themes are detected, published and approved.\n\n## In one picture\n\n```\npush to develop ──► Visual Baseline workflow ──► artifact visual-baseline-<package> (per commit, 90 days)\n\npull request push ──► CI-Pipeline, job visual-tests (<package>)\n compares against the baseline of the base commit\n ──► artifact visual-review-<package> (report.json + changed images)\n │\n ▼\n Visual Review workflow (base repository context)\n publishes visual/pr-<n>/ on GitHub Pages\n reads the reviewers' comments\n sets the commit status \"Visual Review\"\n │\n ▼\nreviewer ──► https://public-ui.github.io/kolibri/visual/?pr=<n>\n inspects baseline / actual / diff, approves or rejects, leaves notes\n saves the review as a pull-request comment (directly with a token, or by pasting it)\n```\n\n## What a contributor sees\n\n- The job `visual-tests (<package>)` of the CI-Pipeline fails when screenshots differ – that is\n expected and not something to \"fix\" by regenerating snapshots. The job summary lists what changed.\n- The bot comment **📸 Visual Review** on the pull request links the review page and shows the counts\n per package.\n- The commit status **Visual Review** stays `pending` until a reviewer with write access approved every\n changed, added and removed screenshot, turns `success` then, and `failure` when a screenshot was\n rejected or a route could not be compared at all (missing block, timeout).\n- Docs-only pull requests get `success` immediately; nothing to review.\n\nNothing has to be committed: the baseline is regenerated from `develop` after the merge.\n\n## What a reviewer does\n\n1. Open the review page from the bot comment (or the status link).\n2. Walk through the changed, added and removed snapshots (`j`/`k` or the list). Compare with\n _side by side_, _slider_, _onion skin_, _diff_ or _blink_; zoom in for subpixel changes.\n3. Approve (`a`), reject or annotate each one – or **Approve all open changes** for an intentional\n sweep such as a browser upgrade.\n4. Save the review:\n - **with a token**: enter a fine-grained personal access token with _Pull requests: read and write_\n for `public-ui/kolibri` at the bottom of the page. The page posts (and later edits) one comment\n in your name. The token stays in this browser session unless you tick \"remember\".\n - **without a token**: click _Copy comment for the pull request_ and paste it as a comment on the\n pull request.\n\nThe comment carries a machine-readable block, for example:\n\n```markdown\n<!-- visual-review:v1\n{\"approveAll\":{\"digest\":\"sha256:…\"},\"approvals\":[{\"item\":\"theme-default/button-basic--variants\",\"hash\":\"sha256:…\"}],\"rejects\":[],\"notes\":[]}\n-->\n\n**Visual Review** – all changes approved ([review page](…))\n```\n\nApprovals bind to the **content hash** of a screenshot, not to a commit: a later push that leaves an\napproved screenshot untouched keeps its approval, a push that changes it again reopens exactly that\none. `approveAll` binds to the digest of the whole report and therefore expires with the next change.\n\nOnly comments of users with write access count. Bots are ignored. A rejection wins over an approval.\n\n## Where things live\n\n| What | Where |\n| -------------------------------- | ------------------------------------------------------------------------------------- |\n| Report per package (CI artifact) | `visual-review-<package>` – `report.json` + PNGs of changed items, 14 days |\n| Baseline per base commit | `visual-baseline-<package>` – snapshots + `meta.json`, 90 days |\n| Published review data | `gh-pages`: `visual/pr-<n>/report.json`, `status.json`, `<package>/<name>.<kind>.png` |\n| Review page | `gh-pages`: `visual/` (built from `packages/tools/visual-tests/review-ui`) |\n| Reporter | `packages/tools/visual-tests/src/visual-reporter.js` |\n| Workflow scripts | `scripts/visual-review/` (see `scripts/README.md`) |\n| Workflows | `visual-baseline.yml`, `visual-review.yml`, `visual-review-ui.yml`, job in `ci.yml` |\n\nThe folder `visual/pr-<n>/` is removed when the pull request closes (`pr-preview-cleanup.yml`).\n\n## Trust boundary\n\nThe reports come from the pull request's own CI run, i.e. from code the pull request controls. The\nVisual Review workflow never executes that code: it downloads the artifacts, validates every field and\nfile name (`merge-reports.mjs`) and publishes only what passes. A pull request could still upload a\nreport that claims \"no changes\" – the human review of the code and the branch protection remain the\nactual safeguard; the visual review makes intentional changes visible and reviewable, it does not\nreplace code review.\n\n## Local work\n\n```bash\npnpm snapshots:pull # fetch the current develop baseline into the snapshot folders\npnpm --filter @public-ui/theme-default test\npnpm --filter @public-ui/visual-tests review-ui:dev # the review page against a local report: ?src=<folder>\n```\n\n`pnpm test:update:docker <theme>` regenerates a baseline locally in the pinned Playwright container.\n",
|
|
513
|
+
"kind": "doc"
|
|
514
|
+
},
|
|
507
515
|
{
|
|
508
516
|
"id": "doc/WORKFLOW_OPTIMIZATION_PLAN",
|
|
509
517
|
"group": "docs",
|
|
@@ -605,7 +613,7 @@
|
|
|
605
613
|
"group": "button-link",
|
|
606
614
|
"name": "basic",
|
|
607
615
|
"path": "packages/samples/react/src/components/button-link/basic.tsx",
|
|
608
|
-
"code": "import
|
|
616
|
+
"code": "import { KolButtonLink, KolHeading } from '@public-ui/react-v19';\nimport type { FC } from 'react';\nimport React from 'react';\nimport { useAlert } from '../../hooks/useAlert';\nimport { SampleBlock } from '../SampleBlock';\nimport { SampleDescription } from '../SampleDescription';\n\nexport const ButtonLinkBasic: FC = () => {\n\tconst { dummyClickEventHandler } = useAlert();\n\n\tconst dummyEventHandler = {\n\t\tonClick: dummyClickEventHandler,\n\t};\n\treturn (\n\t\t<>\n\t\t\t<SampleDescription>\n\t\t\t\t<p>\n\t\t\t\t\tKolButtonLink shows an element, that behaves like a button but looks like a link. The sample illustrates KolButtonLink with different\n\t\t\t\t\tdisplay-properties such as <code>block</code>, <code>inline-block</code> and <code>inline</code>. It also demonstrates the disabled-state.\n\t\t\t\t</p>\n\t\t\t</SampleDescription>\n\t\t\t<KolHeading _level={2} _label=\"Button-Link with _inline\" />\n\n\t\t\t<p>\n\t\t\t\tIn this paragraph, a link is inserted that contains no additional attributes. <KolButtonLink _label=\"Simple Link\" /> It is rendered by default as an{' '}\n\t\t\t\t<strong>inline element</strong>.\n\t\t\t</p>\n\t\t\t<p>\n\t\t\t\tIn this paragraph, a link is inserted that is rendered as an inline-block element.\n\t\t\t\t<KolButtonLink className=\"m-4\" style={{ display: 'inline-block', border: '1px dotted' }} _label=\"Simple Link\" />. This allows you to assign width,\n\t\t\t\theight, and other properties to it using CSS styles.\n\t\t\t\t<br />\n\t\t\t\t<br />\n\t\t\t\tAfter that, there is a link that is rendered as a block element.\n\t\t\t\t<KolButtonLink style={{ display: 'block' }} _label=\"Simple Link\" />\n\t\t\t\tTherefore, I go over the entire width of the parent element to create a line break.\n\t\t\t</p>\n\n\t\t\t<KolHeading _level={2} _label=\"Button-Link with _inline={false}\" />\n\n\t\t\t<p>Use the boolean _inline property to render the link inline (default) or standalone.</p>\n\n\t\t\t<SampleBlock id=\"basic\" className=\"flex flex-col gap-2\" fitContent>\n\t\t\t\t<KolButtonLink _label=\"Standalone ButtonLink\" _inline={false} _on={dummyEventHandler} />\n\t\t\t</SampleBlock>\n\t\t\t<SampleBlock id=\"disabled\" className=\"flex flex-col gap-2\" fitContent>\n\t\t\t\t<KolButtonLink _label=\"Disabled ButtonLink\" _disabled _inline={false} />\n\t\t\t</SampleBlock>\n\t\t\t<SampleBlock id=\"access-key\" className=\"flex flex-col gap-2\" fitContent>\n\t\t\t\t<KolButtonLink _label=\"With access key\" _accessKey=\"c\" _inline={false} _on={dummyEventHandler} />\n\t\t\t</SampleBlock>\n\t\t\t<SampleBlock id=\"short-key\" className=\"flex flex-col gap-2\" fitContent>\n\t\t\t\t<KolButtonLink _label=\"With short key\" _shortKey=\"s\" _inline={false} _on={dummyEventHandler} />\n\t\t\t</SampleBlock>\n\t\t\t<SampleBlock id=\"variant\" className=\"flex flex-col gap-2\" fitContent>\n\t\t\t\t<KolButtonLink _label=\"Special Variant ButtonLink\" _variant=\"theme-link\" />\n\t\t\t</SampleBlock>\n\t\t</>\n\t);\n};\n",
|
|
609
617
|
"kind": "sample"
|
|
610
618
|
},
|
|
611
619
|
{
|
|
@@ -629,7 +637,7 @@
|
|
|
629
637
|
"group": "button",
|
|
630
638
|
"name": "access-key",
|
|
631
639
|
"path": "packages/samples/react/src/components/button/access-key.tsx",
|
|
632
|
-
"code": "import { KolButton, KolLink } from '@public-ui/react-v19';\nimport type { FC } from 'react';\nimport React from 'react';\nimport {
|
|
640
|
+
"code": "import { KolButton, KolLink } from '@public-ui/react-v19';\nimport type { FC } from 'react';\nimport React from 'react';\nimport { useAlert } from '../../hooks/useAlert';\nimport { SampleBlock } from '../SampleBlock';\nimport { SampleDescription } from '../SampleDescription';\n\nexport const ButtonAccessKey: FC = () => {\n\tconst { dummyClickEventHandler } = useAlert();\n\n\tconst dummyEventHandler = {\n\t\tonClick: dummyClickEventHandler,\n\t};\n\n\treturn (\n\t\t<>\n\t\t\t<SampleDescription>\n\t\t\t\t<p>\n\t\t\t\t\tThis story demonstrates buttons with{' '}\n\t\t\t\t\t<KolLink _label=\"access keys\" _href=\"https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/accesskey\" _target=\"blank\" />. Access keys\n\t\t\t\t\tallow users to trigger buttons using keyboard shortcuts.\n\t\t\t\t</p>\n\t\t\t</SampleDescription>\n\n\t\t\t<div className=\"grid gap-8\">\n\t\t\t\t<SampleBlock id=\"buttons-access-keys\" heading=\"Buttons with Access Keys\" fitContent>\n\t\t\t\t\t<div className=\"flex flex-wrap gap-4\">\n\t\t\t\t\t\t<KolButton _label=\"With S access key\" _accessKey=\"S\" _on={dummyEventHandler} />\n\t\t\t\t\t\t<KolButton _label=\"Very small b\" _accessKey=\"b\" _on={dummyEventHandler} />\n\t\t\t\t\t\t<KolButton _label=\"Access key does not appear in label\" _accessKey=\"x\" _on={dummyEventHandler} />\n\t\t\t\t\t</div>\n\t\t\t\t</SampleBlock>\n\n\t\t\t\t<SampleBlock id=\"access-key-hidden-label\" heading=\"Access Key with Hidden Label\" fitContent>\n\t\t\t\t\t<div className=\"flex flex-wrap gap-4\">\n\t\t\t\t\t\t<KolButton _label=\"access key without label\" _hideLabel _accessKey=\"a\" _icons=\"kolicon-cogwheel\" _on={dummyEventHandler} />\n\t\t\t\t\t</div>\n\t\t\t\t</SampleBlock>\n\n\t\t\t\t<SampleBlock id=\"access-key-inline-icons\" heading=\"Access Key with Inline Icons\" fitContent>\n\t\t\t\t\t<div className=\"flex flex-wrap gap-4\">\n\t\t\t\t\t\t<KolButton\n\t\t\t\t\t\t\t_label=\"with inline icons\"\n\t\t\t\t\t\t\t_icons={{\n\t\t\t\t\t\t\t\tleft: 'kolicon-cogwheel',\n\t\t\t\t\t\t\t\tright: 'kolicon-cogwheel',\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t_accessKey=\"n\"\n\t\t\t\t\t\t\t_on={dummyEventHandler}\n\t\t\t\t\t\t/>\n\t\t\t\t\t</div>\n\t\t\t\t</SampleBlock>\n\t\t\t</div>\n\t\t</>\n\t);\n};\n",
|
|
633
641
|
"kind": "sample"
|
|
634
642
|
},
|
|
635
643
|
{
|
|
@@ -637,7 +645,7 @@
|
|
|
637
645
|
"group": "button",
|
|
638
646
|
"name": "aria-description",
|
|
639
647
|
"path": "packages/samples/react/src/components/button/aria-description.tsx",
|
|
640
|
-
"code": "import { KolButton } from '@public-ui/react-v19';\nimport type { FC } from 'react';\nimport React from 'react';\nimport {
|
|
648
|
+
"code": "import { KolButton } from '@public-ui/react-v19';\nimport type { FC } from 'react';\nimport React from 'react';\nimport { useAlert } from '../../hooks/useAlert';\nimport { SampleBlock } from '../SampleBlock';\nimport { SampleDescription } from '../SampleDescription';\n\nexport const ButtonAriaDescription: FC = () => {\n\tconst { dummyClickEventHandler } = useAlert();\n\n\tconst dummyEventHandler = {\n\t\tonClick: dummyClickEventHandler,\n\t};\n\n\treturn (\n\t\t<>\n\t\t\t<SampleDescription>\n\t\t\t\t<p>\n\t\t\t\t\tThis story demonstrates buttons with ARIA descriptions. The aria-description attribute provides additional descriptive text for screen readers,\n\t\t\t\t\thelping users understand the button's purpose or action in more detail.\n\t\t\t\t</p>\n\t\t\t</SampleDescription>\n\n\t\t\t<div className=\"grid gap-8\">\n\t\t\t\t<SampleBlock id=\"buttons-aria-description\" heading=\"Buttons with and without ARIA Description\" fitContent>\n\t\t\t\t\t<div className=\"flex flex-wrap gap-4\">\n\t\t\t\t\t\t<KolButton _label=\"Button without ARIA description\" _on={dummyEventHandler} />\n\t\t\t\t\t\t<KolButton _label=\"Button with ARIA description\" _ariaDescription=\"This button performs an important action\" _on={dummyEventHandler} />\n\t\t\t\t\t</div>\n\t\t\t\t</SampleBlock>\n\t\t\t</div>\n\t\t</>\n\t);\n};\n",
|
|
641
649
|
"kind": "sample"
|
|
642
650
|
},
|
|
643
651
|
{
|
|
@@ -645,7 +653,7 @@
|
|
|
645
653
|
"group": "button",
|
|
646
654
|
"name": "baselined",
|
|
647
655
|
"path": "packages/samples/react/src/components/button/baselined.tsx",
|
|
648
|
-
"code": "import { KolButton } from '@public-ui/react-v19';\nimport type { FC } from 'react';\nimport React from 'react';\nimport {
|
|
656
|
+
"code": "import { KolButton } from '@public-ui/react-v19';\nimport type { FC } from 'react';\nimport React from 'react';\nimport { useAlert } from '../../hooks/useAlert';\nimport { SampleBlock } from '../SampleBlock';\nimport { SampleDescription } from '../SampleDescription';\n\nexport const ButtonBaselined: FC = () => {\n\tconst { dummyClickEventHandler } = useAlert();\n\n\tconst dummyEventHandler = {\n\t\tonClick: dummyClickEventHandler,\n\t};\n\n\treturn (\n\t\t<>\n\t\t\t<SampleDescription>\n\t\t\t\t<p>\n\t\t\t\t\tThis story demonstrates button baseline alignment. It shows multiple buttons with and without icons that are vertically aligned, useful for testing\n\t\t\t\t\tlayout consistency.\n\t\t\t\t</p>\n\t\t\t</SampleDescription>\n\n\t\t\t<div className=\"grid gap-8\">\n\t\t\t\t<SampleBlock id=\"vertically-aligned-buttons\" heading=\"Vertically Aligned Buttons\" fitContent>\n\t\t\t\t\t<div className=\"flex flex-wrap gap-2\">\n\t\t\t\t\t\t<KolButton _label=\"Label-Text\" _on={dummyEventHandler} />\n\t\t\t\t\t\t<KolButton _icons=\"kolicon-cogwheel\" _label=\"Label-Text with Icon\" _on={dummyEventHandler} />\n\t\t\t\t\t</div>\n\t\t\t\t</SampleBlock>\n\t\t\t</div>\n\t\t</>\n\t);\n};\n",
|
|
649
657
|
"kind": "sample"
|
|
650
658
|
},
|
|
651
659
|
{
|
|
@@ -653,7 +661,7 @@
|
|
|
653
661
|
"group": "button",
|
|
654
662
|
"name": "basic",
|
|
655
663
|
"path": "packages/samples/react/src/components/button/basic.tsx",
|
|
656
|
-
"code": "import { KolButton } from '@public-ui/react-v19';\nimport type { FC } from 'react';\nimport React from 'react';\nimport {
|
|
664
|
+
"code": "import { KolButton } from '@public-ui/react-v19';\nimport type { FC } from 'react';\nimport React from 'react';\nimport { useAlert } from '../../hooks/useAlert';\nimport { SampleBlock } from '../SampleBlock';\nimport { SampleDescription } from '../SampleDescription';\n\nexport const ButtonBasic: FC = () => {\n\tconst { dummyClickEventHandler } = useAlert();\n\n\tconst dummyEventHandler = {\n\t\tonClick: dummyClickEventHandler,\n\t};\n\n\treturn (\n\t\t<>\n\t\t\t<SampleDescription>\n\t\t\t\t<p>\n\t\t\t\t\tThis story demonstrates the most important features of the KolButton component. It showcases the different button variants, icons, disabled state, and\n\t\t\t\t\thidden labels.\n\t\t\t\t</p>\n\t\t\t</SampleDescription>\n\n\t\t\t<div className=\"grid gap-8\">\n\t\t\t\t<SampleBlock id=\"variants\" heading=\"Button Variants\" fitContent>\n\t\t\t\t\t<div className=\"flex flex-wrap gap-4\">\n\t\t\t\t\t\t<KolButton _icons=\"kolicon-house\" _label=\"Primary\" _variant=\"primary\" onClick={dummyClickEventHandler} />\n\t\t\t\t\t\t<KolButton _icons=\"kolicon-kolibri\" _label=\"Secondary\" _variant=\"secondary\" onClick={dummyClickEventHandler} />\n\t\t\t\t\t\t<KolButton _icons=\"kolicon-cogwheel\" _label=\"Tertiary\" _variant=\"tertiary\" onClick={dummyClickEventHandler} />\n\t\t\t\t\t\t<KolButton _icons=\"kolicon-cogwheel\" _label=\"Normal\" _variant=\"normal\" _on={dummyEventHandler} />\n\t\t\t\t\t\t<KolButton _icons=\"kolicon-alert-warning\" _label=\"Danger\" _variant=\"danger\" _on={dummyEventHandler} />\n\t\t\t\t\t\t<KolButton _icons=\"kolicon-eye-closed\" _label=\"Ghost\" _variant=\"ghost\" _on={dummyEventHandler} />\n\t\t\t\t\t</div>\n\t\t\t\t</SampleBlock>\n\n\t\t\t\t<SampleBlock id=\"disabled\" heading=\"Disabled State\" fitContent>\n\t\t\t\t\t<div className=\"flex flex-wrap gap-4\">\n\t\t\t\t\t\t<KolButton _disabled _icons=\"kolicon-house\" _label=\"Primary\" _variant=\"primary\" _on={dummyEventHandler} />\n\t\t\t\t\t\t<KolButton _disabled _icons=\"kolicon-kolibri\" _label=\"Secondary\" _variant=\"secondary\" _on={dummyEventHandler} />\n\t\t\t\t\t\t<KolButton _disabled _icons=\"kolicon-alert-warning\" _label=\"Danger\" _variant=\"danger\" _on={dummyEventHandler} />\n\t\t\t\t\t</div>\n\t\t\t\t</SampleBlock>\n\n\t\t\t\t<SampleBlock id=\"hide-label\" heading=\"Hidden Label (Icon Only)\" fitContent>\n\t\t\t\t\t<div className=\"flex flex-wrap gap-4\">\n\t\t\t\t\t\t<KolButton _hideLabel _icons=\"kolicon-house\" _label=\"Primary\" _variant=\"primary\" _on={dummyEventHandler} />\n\t\t\t\t\t\t<KolButton _hideLabel _icons=\"kolicon-kolibri\" _label=\"Secondary\" _variant=\"secondary\" _on={dummyEventHandler} />\n\t\t\t\t\t\t<KolButton _hideLabel _icons=\"kolicon-alert-warning\" _label=\"Danger\" _variant=\"danger\" _on={dummyEventHandler} />\n\t\t\t\t\t</div>\n\t\t\t\t</SampleBlock>\n\n\t\t\t\t<SampleBlock id=\"icon-positions\" heading=\"Icon Positions\" fitContent>\n\t\t\t\t\t<div className=\"flex flex-wrap gap-4\">\n\t\t\t\t\t\t<KolButton\n\t\t\t\t\t\t\t_icons={{\n\t\t\t\t\t\t\t\tleft: 'kolicon-chevron-left',\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t_label=\"Icon Left\"\n\t\t\t\t\t\t\t_on={dummyEventHandler}\n\t\t\t\t\t\t/>\n\t\t\t\t\t\t<KolButton\n\t\t\t\t\t\t\t_icons={{\n\t\t\t\t\t\t\t\tright: 'kolicon-chevron-right',\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t_label=\"Icon Right\"\n\t\t\t\t\t\t\t_on={dummyEventHandler}\n\t\t\t\t\t\t/>\n\t\t\t\t\t\t<KolButton\n\t\t\t\t\t\t\t_icons={{\n\t\t\t\t\t\t\t\tleft: 'kolicon-chevron-left',\n\t\t\t\t\t\t\t\tright: 'kolicon-chevron-right',\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t_label=\"Icons Both Sides\"\n\t\t\t\t\t\t\t_on={dummyEventHandler}\n\t\t\t\t\t\t/>\n\t\t\t\t\t</div>\n\t\t\t\t</SampleBlock>\n\t\t\t</div>\n\t\t</>\n\t);\n};\n",
|
|
657
665
|
"kind": "sample"
|
|
658
666
|
},
|
|
659
667
|
{
|
|
@@ -661,7 +669,7 @@
|
|
|
661
669
|
"group": "button",
|
|
662
670
|
"name": "disabled",
|
|
663
671
|
"path": "packages/samples/react/src/components/button/disabled.tsx",
|
|
664
|
-
"code": "import { KolButton } from '@public-ui/react-v19';\nimport type { FC } from 'react';\nimport React from 'react';\nimport {
|
|
672
|
+
"code": "import { KolButton } from '@public-ui/react-v19';\nimport type { FC } from 'react';\nimport React from 'react';\nimport { useAlert } from '../../hooks/useAlert';\nimport { SampleBlock } from '../SampleBlock';\nimport { SampleDescription } from '../SampleDescription';\n\nexport const ButtonDisabled: FC = () => {\n\tconst { dummyClickEventHandler } = useAlert();\n\n\tconst dummyEventHandler = {\n\t\tonClick: dummyClickEventHandler,\n\t};\n\n\treturn (\n\t\t<>\n\t\t\t<SampleDescription>\n\t\t\t\t<p>This story demonstrates the disabled state of buttons. Disabled buttons are not clickable and appear visually dimmed.</p>\n\t\t\t</SampleDescription>\n\n\t\t\t<div className=\"grid gap-8\">\n\t\t\t\t<SampleBlock id=\"disabled\" heading=\"Disabled Buttons\" fitContent>\n\t\t\t\t\t<div className=\"flex flex-wrap gap-4\">\n\t\t\t\t\t\t<KolButton _disabled _icons=\"kolicon-house\" _label=\"Primary\" _variant=\"primary\" _on={dummyEventHandler} />\n\t\t\t\t\t\t<KolButton _disabled _icons=\"kolicon-kolibri\" _label=\"Secondary\" _variant=\"secondary\" _on={dummyEventHandler} />\n\t\t\t\t\t\t<KolButton _disabled _icons=\"kolicon-cogwheel\" _label=\"Tertiary\" _variant=\"tertiary\" _on={dummyEventHandler} />\n\t\t\t\t\t\t<KolButton _disabled _icons=\"kolicon-cogwheel\" _label=\"Normal\" _variant=\"normal\" _on={dummyEventHandler} />\n\t\t\t\t\t\t<KolButton _disabled _icons=\"kolicon-alert-warning\" _label=\"Danger\" _variant=\"danger\" _on={dummyEventHandler} />\n\t\t\t\t\t\t<KolButton _disabled _icons=\"kolicon-eye-closed\" _label=\"Ghost\" _variant=\"ghost\" _on={dummyEventHandler} />\n\t\t\t\t\t</div>\n\t\t\t\t</SampleBlock>\n\n\t\t\t\t<SampleBlock id=\"comparison\" heading=\"Comparison: Enabled vs Disabled\" fitContent>\n\t\t\t\t\t<div className=\"flex flex-wrap gap-4\">\n\t\t\t\t\t\t<KolButton _icons=\"kolicon-house\" _label=\"Enabled\" _variant=\"primary\" _on={dummyEventHandler} />\n\t\t\t\t\t\t<KolButton _disabled _icons=\"kolicon-house\" _label=\"Disabled\" _variant=\"primary\" _on={dummyEventHandler} />\n\t\t\t\t\t</div>\n\t\t\t\t</SampleBlock>\n\t\t\t</div>\n\t\t</>\n\t);\n};\n",
|
|
665
673
|
"kind": "sample"
|
|
666
674
|
},
|
|
667
675
|
{
|
|
@@ -669,7 +677,7 @@
|
|
|
669
677
|
"group": "button",
|
|
670
678
|
"name": "expert-slot",
|
|
671
679
|
"path": "packages/samples/react/src/components/button/expert-slot.tsx",
|
|
672
|
-
"code": "import { KolButton, KolIcon } from '@public-ui/react-v19';\nimport type { FC } from 'react';\nimport React from 'react';\nimport {
|
|
680
|
+
"code": "import { KolButton, KolIcon } from '@public-ui/react-v19';\nimport type { FC } from 'react';\nimport React from 'react';\nimport { useAlert } from '../../hooks/useAlert';\nimport { SampleBlock } from '../SampleBlock';\nimport { SampleDescription } from '../SampleDescription';\n\nimport './expert-slot.tooltip.scss';\n\nconst KolTooltip = 'kol-tooltip-wc' as unknown as React.FC<{ _label: string }>;\n\nexport const ButtonExpertSlot: FC = () => {\n\tconst { dummyClickEventHandler } = useAlert();\n\n\tconst dummyEventHandler = {\n\t\tonClick: dummyClickEventHandler,\n\t};\n\n\treturn (\n\t\t<>\n\t\t\t<SampleDescription>\n\t\t\t\t<p>\n\t\t\t\t\tThis story demonstrates the expert slot feature of KolButton. The expert slot allows you to insert custom content into the button, providing advanced\n\t\t\t\t\tcustomization options beyond the standard label and icon properties.\n\t\t\t\t</p>\n\t\t\t</SampleDescription>\n\n\t\t\t<div className=\"grid gap-8\">\n\t\t\t\t<SampleBlock id=\"buttons-expert-slot-content\" heading=\"Buttons with Expert Slot Content\" fitContent>\n\t\t\t\t\t<div className=\"flex flex-wrap gap-4\">\n\t\t\t\t\t\t<KolButton _icons=\"kolicon-house\" _label=\"\" _variant=\"primary\" _on={dummyEventHandler}>\n\t\t\t\t\t\t\t<span slot=\"expert\">I am more than just a button</span>\n\t\t\t\t\t\t</KolButton>\n\t\t\t\t\t\t<KolButton _icons=\"kolicon-kolibri\" _label=\"\" _variant=\"secondary\" _on={dummyEventHandler}>\n\t\t\t\t\t\t\t<span slot=\"expert\">Custom content here</span>\n\t\t\t\t\t\t</KolButton>\n\t\t\t\t\t\t<KolButton _icons=\"kolicon-alert-warning\" _label=\"\" _variant=\"danger\" _on={dummyEventHandler}>\n\t\t\t\t\t\t\t<span slot=\"expert\">Delete with custom text</span>\n\t\t\t\t\t\t</KolButton>\n\t\t\t\t\t\t<KolButton _label=\"\" _variant=\"danger\" _on={dummyEventHandler}>\n\t\t\t\t\t\t\t<KolIcon _icons=\"kolicon-alert-warning\" _label=\"Delete with custom text\" slot=\"expert\" />\n\t\t\t\t\t\t</KolButton>\n\t\t\t\t\t\t<KolTooltip _label=\"Delete with custom text\" />\n\t\t\t\t\t</div>\n\t\t\t\t</SampleBlock>\n\n\t\t\t\t<SampleBlock id=\"disabled-buttons-expert-slot\" heading=\"Disabled Buttons with Expert Slot\" fitContent>\n\t\t\t\t\t<div className=\"flex flex-wrap gap-4\">\n\t\t\t\t\t\t<KolButton _disabled _icons=\"kolicon-house\" _label=\"\" _variant=\"primary\" _on={dummyEventHandler}>\n\t\t\t\t\t\t\t<span slot=\"expert\">Disabled expert slot</span>\n\t\t\t\t\t\t</KolButton>\n\t\t\t\t\t\t<KolButton _disabled _icons=\"kolicon-eye-closed\" _label=\"\" _variant=\"ghost\" _on={dummyEventHandler}>\n\t\t\t\t\t\t\t<span slot=\"expert\">Another disabled one</span>\n\t\t\t\t\t\t</KolButton>\n\t\t\t\t\t</div>\n\t\t\t\t</SampleBlock>\n\t\t\t</div>\n\t\t</>\n\t);\n};\n",
|
|
673
681
|
"kind": "sample"
|
|
674
682
|
},
|
|
675
683
|
{
|
|
@@ -677,7 +685,7 @@
|
|
|
677
685
|
"group": "button",
|
|
678
686
|
"name": "fixed-grid",
|
|
679
687
|
"path": "packages/samples/react/src/components/button/buttons-in-fixed-grid.tsx",
|
|
680
|
-
"code": "import { KolButton, KolLinkButton } from '@public-ui/react-v19';\nimport type { FC } from 'react';\nimport React from 'react';\nimport {
|
|
688
|
+
"code": "import { KolButton, KolLinkButton } from '@public-ui/react-v19';\nimport type { FC } from 'react';\nimport React from 'react';\nimport { useAlert } from '../../hooks/useAlert';\nimport { SampleDescription } from '../SampleDescription';\n\nexport const ButtonInFixedGrid: FC = () => {\n\tconst { dummyClickEventHandler } = useAlert();\n\n\tconst dummyEventHandler = {\n\t\tonClick: dummyClickEventHandler,\n\t};\n\n\treturn (\n\t\t<>\n\t\t\t<SampleDescription>\n\t\t\t\t<p>All this buttons are in a grid with fixed height (60px) and width (25% of screen) and should accept this dimensions.</p>\n\t\t\t</SampleDescription>\n\t\t\t<div className=\"grid gap-4 fixed-height-grid\">\n\t\t\t\t<KolButton _variant=\"primary\" _icons=\"kolicon-house\" _label=\"Button\" _on={dummyEventHandler} />\n\t\t\t\t<KolButton _variant=\"primary\" _hideLabel _icons=\"kolicon-house\" _label=\"Button\" _on={dummyEventHandler} />\n\t\t\t\t<KolLinkButton _variant=\"primary\" _href=\"#\" _icons=\"kolicon-house\" _label=\"Link-Button\" _on={dummyEventHandler} />\n\t\t\t\t<KolLinkButton _variant=\"primary\" _hideLabel _href=\"#\" _icons=\"kolicon-house\" _label=\"Link-Button\" _on={dummyEventHandler} />\n\t\t\t</div>\n\t\t</>\n\t);\n};\n",
|
|
681
689
|
"kind": "sample"
|
|
682
690
|
},
|
|
683
691
|
{
|
|
@@ -693,7 +701,7 @@
|
|
|
693
701
|
"group": "button",
|
|
694
702
|
"name": "hide-label",
|
|
695
703
|
"path": "packages/samples/react/src/components/button/hide-label.tsx",
|
|
696
|
-
"code": "import { KolButton } from '@public-ui/react-v19';\nimport type { FC } from 'react';\nimport React from 'react';\nimport {
|
|
704
|
+
"code": "import { KolButton } from '@public-ui/react-v19';\nimport type { FC } from 'react';\nimport React from 'react';\nimport { useAlert } from '../../hooks/useAlert';\nimport { SampleBlock } from '../SampleBlock';\nimport { SampleDescription } from '../SampleDescription';\n\nexport const ButtonHideLabel: FC = () => {\n\tconst { dummyClickEventHandler } = useAlert();\n\n\tconst dummyEventHandler = {\n\t\tonClick: dummyClickEventHandler,\n\t};\n\n\treturn (\n\t\t<>\n\t\t\t<SampleDescription>\n\t\t\t\t<p>\n\t\t\t\t\tThis story demonstrates buttons with hidden labels. The label is still accessible to screen readers but visually hidden, showing only the icon. This\n\t\t\t\t\tis useful for icon-only buttons.\n\t\t\t\t</p>\n\t\t\t</SampleDescription>\n\n\t\t\t<div className=\"grid gap-8\">\n\t\t\t\t<SampleBlock id=\"hide-label\" heading=\"Buttons with Hidden Labels\" fitContent>\n\t\t\t\t\t<div className=\"flex flex-wrap gap-4\">\n\t\t\t\t\t\t<KolButton _hideLabel _icons=\"kolicon-house\" _label=\"Home\" _variant=\"primary\" _on={dummyEventHandler} />\n\t\t\t\t\t\t<KolButton _hideLabel _icons=\"kolicon-kolibri\" _label=\"Like\" _variant=\"secondary\" _on={dummyEventHandler} />\n\t\t\t\t\t\t<KolButton _hideLabel _icons=\"kolicon-cogwheel\" _label=\"Subscribe\" _variant=\"tertiary\" _on={dummyEventHandler} />\n\t\t\t\t\t\t<KolButton _hideLabel _icons=\"kolicon-cogwheel\" _label=\"Buy me a coffee\" _variant=\"normal\" _on={dummyEventHandler} />\n\t\t\t\t\t\t<KolButton _hideLabel _icons=\"kolicon-alert-warning\" _label=\"Delete\" _variant=\"danger\" _on={dummyEventHandler} />\n\t\t\t\t\t\t<KolButton _hideLabel _icons=\"kolicon-eye-closed\" _label=\"Settings\" _variant=\"ghost\" _on={dummyEventHandler} />\n\t\t\t\t\t</div>\n\t\t\t\t</SampleBlock>\n\n\t\t\t\t<SampleBlock id=\"comparison\" heading=\"Comparison: With and Without Hidden Label\" fitContent>\n\t\t\t\t\t<div className=\"flex flex-wrap gap-4\">\n\t\t\t\t\t\t<KolButton _icons=\"kolicon-house\" _label=\"Home\" _variant=\"primary\" _on={dummyEventHandler} />\n\t\t\t\t\t\t<KolButton _hideLabel _icons=\"kolicon-house\" _label=\"Home\" _variant=\"primary\" _on={dummyEventHandler} />\n\t\t\t\t\t</div>\n\t\t\t\t</SampleBlock>\n\n\t\t\t\t<SampleBlock id=\"disabled\" heading=\"Disabled with Hidden Label\" fitContent>\n\t\t\t\t\t<div className=\"flex flex-wrap gap-4\">\n\t\t\t\t\t\t<KolButton _disabled _hideLabel _icons=\"kolicon-house\" _label=\"Home\" _variant=\"primary\" _on={dummyEventHandler} />\n\t\t\t\t\t\t<KolButton _disabled _hideLabel _icons=\"kolicon-kolibri\" _label=\"Like\" _variant=\"secondary\" _on={dummyEventHandler} />\n\t\t\t\t\t\t<KolButton _disabled _hideLabel _icons=\"kolicon-cogwheel\" _label=\"Subscribe\" _variant=\"tertiary\" _on={dummyEventHandler} />\n\t\t\t\t\t\t<KolButton _disabled _hideLabel _icons=\"kolicon-cogwheel\" _label=\"Buy me a coffee\" _variant=\"normal\" _on={dummyEventHandler} />\n\t\t\t\t\t\t<KolButton _disabled _hideLabel _icons=\"kolicon-alert-warning\" _label=\"Delete\" _variant=\"danger\" _on={dummyEventHandler} />\n\t\t\t\t\t</div>\n\t\t\t\t</SampleBlock>\n\t\t\t</div>\n\t\t</>\n\t);\n};\n",
|
|
697
705
|
"kind": "sample"
|
|
698
706
|
},
|
|
699
707
|
{
|
|
@@ -701,7 +709,7 @@
|
|
|
701
709
|
"group": "button",
|
|
702
710
|
"name": "icons",
|
|
703
711
|
"path": "packages/samples/react/src/components/button/icons.tsx",
|
|
704
|
-
"code": "import { KolButton } from '@public-ui/react-v19';\nimport type { FC } from 'react';\nimport React from 'react';\nimport {
|
|
712
|
+
"code": "import { KolButton } from '@public-ui/react-v19';\nimport type { FC } from 'react';\nimport React from 'react';\nimport { useAlert } from '../../hooks/useAlert';\nimport { SampleBlock } from '../SampleBlock';\nimport { SampleDescription } from '../SampleDescription';\n\nexport const ButtonIcons: FC = () => {\n\tconst { dummyClickEventHandler } = useAlert();\n\tconst dummyEventHandler = {\n\t\tonClick: dummyClickEventHandler,\n\t};\n\n\treturn (\n\t\t<>\n\t\t\t<SampleDescription>\n\t\t\t\t<p>\n\t\t\t\t\tThis story showcases buttons with icons in various positions and configurations. Icons can be placed on the left, right, top, bottom, or in multiple\n\t\t\t\t\tpositions at once.\n\t\t\t\t</p>\n\t\t\t</SampleDescription>\n\n\t\t\t<div className=\"grid gap-8\">\n\t\t\t\t<SampleBlock id=\"basic-positions\" heading=\"Basic Icon Positions\" fitContent>\n\t\t\t\t\t<div className=\"flex flex-wrap gap-4\">\n\t\t\t\t\t\t<KolButton\n\t\t\t\t\t\t\t_icons={{\n\t\t\t\t\t\t\t\tleft: 'kolicon-chevron-left',\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t_label=\"Icon Left\"\n\t\t\t\t\t\t\t_on={dummyEventHandler}\n\t\t\t\t\t\t/>\n\t\t\t\t\t\t<KolButton\n\t\t\t\t\t\t\t_icons={{\n\t\t\t\t\t\t\t\tright: 'kolicon-chevron-right',\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t_label=\"Icon Right\"\n\t\t\t\t\t\t\t_on={dummyEventHandler}\n\t\t\t\t\t\t/>\n\t\t\t\t\t\t<KolButton\n\t\t\t\t\t\t\t_icons={{\n\t\t\t\t\t\t\t\ttop: 'kolicon-chevron-up',\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t_label=\"Icon Top\"\n\t\t\t\t\t\t\t_on={dummyEventHandler}\n\t\t\t\t\t\t/>\n\t\t\t\t\t\t<KolButton\n\t\t\t\t\t\t\t_icons={{\n\t\t\t\t\t\t\t\tbottom: 'kolicon-chevron-down',\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t_label=\"Icon Bottom\"\n\t\t\t\t\t\t\t_on={dummyEventHandler}\n\t\t\t\t\t\t/>\n\t\t\t\t\t</div>\n\t\t\t\t</SampleBlock>\n\n\t\t\t\t<SampleBlock id=\"multiple-positions\" heading=\"Multiple Icon Positions\" fitContent>\n\t\t\t\t\t<div className=\"flex flex-wrap gap-4\">\n\t\t\t\t\t\t<KolButton\n\t\t\t\t\t\t\t_icons={{\n\t\t\t\t\t\t\t\tleft: 'kolicon-chevron-left',\n\t\t\t\t\t\t\t\tright: 'kolicon-chevron-right',\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t_label=\"Left & Right\"\n\t\t\t\t\t\t\t_on={dummyEventHandler}\n\t\t\t\t\t\t/>\n\t\t\t\t\t\t<KolButton\n\t\t\t\t\t\t\t_icons={{\n\t\t\t\t\t\t\t\ttop: 'kolicon-chevron-up',\n\t\t\t\t\t\t\t\tbottom: 'kolicon-chevron-down',\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t_label=\"Top & Bottom\"\n\t\t\t\t\t\t\t_on={dummyEventHandler}\n\t\t\t\t\t\t/>\n\t\t\t\t\t</div>\n\t\t\t\t</SampleBlock>\n\n\t\t\t\t<SampleBlock id=\"all-positions\" heading=\"All Icon Positions\" fitContent>\n\t\t\t\t\t<div className=\"flex flex-wrap gap-4\">\n\t\t\t\t\t\t<KolButton\n\t\t\t\t\t\t\t_icons={{\n\t\t\t\t\t\t\t\ttop: 'kolicon-chevron-up',\n\t\t\t\t\t\t\t\tbottom: 'kolicon-chevron-down',\n\t\t\t\t\t\t\t\tleft: 'kolicon-chevron-left',\n\t\t\t\t\t\t\t\tright: 'kolicon-chevron-right',\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t_label=\"All Directions\"\n\t\t\t\t\t\t\t_on={dummyEventHandler}\n\t\t\t\t\t\t/>\n\t\t\t\t\t</div>\n\t\t\t\t</SampleBlock>\n\n\t\t\t\t<SampleBlock id=\"icon-string\" heading=\"Simple Icon String\" fitContent>\n\t\t\t\t\t<div className=\"flex flex-wrap gap-4\">\n\t\t\t\t\t\t<KolButton _icons=\"kolicon-house\" _label=\"Home Icon\" _on={dummyEventHandler} />\n\t\t\t\t\t\t<KolButton _icons=\"kolicon-kolibri\" _label=\"Heart Icon\" _on={dummyEventHandler} />\n\t\t\t\t\t\t<KolButton _icons=\"kolicon-alert-warning\" _label=\"Trash Icon\" _on={dummyEventHandler} />\n\t\t\t\t\t</div>\n\t\t\t\t</SampleBlock>\n\n\t\t\t\t<SampleBlock id=\"large-icon\" heading=\"Large Icon on Top\" fitContent>\n\t\t\t\t\t<div className=\"flex flex-wrap gap-4\">\n\t\t\t\t\t\t<KolButton\n\t\t\t\t\t\t\t_icons={{\n\t\t\t\t\t\t\t\ttop: {\n\t\t\t\t\t\t\t\t\tstyle: {\n\t\t\t\t\t\t\t\t\t\t'font-size': '400%',\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\ticon: 'kolicon-house',\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t_label=\"Home\"\n\t\t\t\t\t\t\t_on={dummyEventHandler}\n\t\t\t\t\t\t/>\n\t\t\t\t\t</div>\n\t\t\t\t</SampleBlock>\n\t\t\t</div>\n\t\t</>\n\t);\n};\n",
|
|
705
713
|
"kind": "sample"
|
|
706
714
|
},
|
|
707
715
|
{
|
|
@@ -717,7 +725,7 @@
|
|
|
717
725
|
"group": "button",
|
|
718
726
|
"name": "short-key",
|
|
719
727
|
"path": "packages/samples/react/src/components/button/short-key.tsx",
|
|
720
|
-
"code": "import { KolAlert, KolButton, KolLink } from '@public-ui/react-v19';\nimport type { FC } from 'react';\nimport React from 'react';\nimport {
|
|
728
|
+
"code": "import { KolAlert, KolButton, KolLink } from '@public-ui/react-v19';\nimport type { FC } from 'react';\nimport React from 'react';\nimport { useAlert } from '../../hooks/useAlert';\nimport { SampleBlock } from '../SampleBlock';\nimport { SampleDescription } from '../SampleDescription';\n\nexport const ButtonShortKey: FC = () => {\n\tconst { dummyClickEventHandler } = useAlert();\n\n\tconst dummyEventHandler = {\n\t\tonClick: dummyClickEventHandler,\n\t};\n\n\t// The short key announced via `_shortKey` is purely visual/assistive – it does NOT\n\t// wire up a keyboard handler. The example below shows how to make it interactive by\n\t// registering a matching `keydown` listener yourself.\n\tconst interactiveShortKey = 'm';\n\t// Keep a stable reference to the (per-render) handler so the global listener is\n\t// registered only once instead of on every render.\n\tconst dummyClickEventHandlerRef = React.useRef(dummyClickEventHandler);\n\tReact.useEffect(() => {\n\t\tdummyClickEventHandlerRef.current = dummyClickEventHandler;\n\t}, [dummyClickEventHandler]);\n\tReact.useEffect(() => {\n\t\tconst handleKeyDown = (event: KeyboardEvent) => {\n\t\t\t// Match on `event.code` (layout-independent): on macOS, Alt + M emits a special\n\t\t\t// character, so `event.key` would not equal \"m\".\n\t\t\tif (event.altKey && event.code === 'KeyM') {\n\t\t\t\tevent.preventDefault();\n\t\t\t\tdummyClickEventHandlerRef.current();\n\t\t\t}\n\t\t};\n\t\tdocument.addEventListener('keydown', handleKeyDown);\n\t\treturn () => document.removeEventListener('keydown', handleKeyDown);\n\t}, []);\n\n\treturn (\n\t\t<>\n\t\t\t<SampleDescription>\n\t\t\t\t<p>\n\t\t\t\t\tThis story demonstrates buttons with short keys. The short key is displayed as a visual indicator within the button label to communicate a recommended\n\t\t\t\t\tkeyboard shortcut to the user.\n\t\t\t\t</p>\n\t\t\t</SampleDescription>\n\n\t\t\t<KolAlert _label=\"Short keys are display-only\" _type=\"info\" _variant=\"card\">\n\t\t\t\t<p>\n\t\t\t\t\t<code>_shortKey</code> is <strong>purely visual and assistive</strong>: it renders the badge and announces the shortcut via{' '}\n\t\t\t\t\t<code>aria-keyshortcuts</code>, but it does <strong>not</strong> bind a keyboard handler. Pressing the displayed combination on its own does nothing –\n\t\t\t\t\tyou have to register the listener yourself (see the interactive example below).\n\t\t\t\t</p>\n\t\t\t\t<p>\n\t\t\t\t\tIf you need a native, browser-handled shortcut instead, use{' '}\n\t\t\t\t\t<KolLink _label=\"_accessKey\" _href=\"https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/accesskey\" _target=\"_blank\" />. Note that\n\t\t\t\t\tnative access keys are triggered in a browser-specific way (e.g. <kbd>Alt</kbd> + <kbd>Shift</kbd> + key in Chrome on Windows).\n\t\t\t\t</p>\n\t\t\t</KolAlert>\n\n\t\t\t<div className=\"grid gap-8\">\n\t\t\t\t<SampleBlock id=\"short-keys\" heading=\"Buttons with Short Keys\" fitContent>\n\t\t\t\t\t<div className=\"flex flex-wrap gap-4\">\n\t\t\t\t\t\t<KolButton _label=\"With S short key\" _shortKey=\"S\" _on={dummyEventHandler} />\n\t\t\t\t\t\t<KolButton _label=\"Very small b\" _shortKey=\"b\" _on={dummyEventHandler} />\n\t\t\t\t\t\t<KolButton _label=\"Short key does not appear in label\" _shortKey=\"x\" _on={dummyEventHandler} />\n\t\t\t\t\t</div>\n\t\t\t\t</SampleBlock>\n\n\t\t\t\t<SampleBlock id=\"hide-label\" heading=\"Short Key with Hidden Label\" fitContent>\n\t\t\t\t\t<div className=\"flex flex-wrap gap-4\">\n\t\t\t\t\t\t<KolButton _label=\"short key without label\" _hideLabel _shortKey=\"k\" _icons=\"kolicon-cogwheel\" _on={dummyEventHandler} />\n\t\t\t\t\t</div>\n\t\t\t\t</SampleBlock>\n\n\t\t\t\t<SampleBlock id=\"inline-icons\" heading=\"Short Key with Inline Icons\" fitContent>\n\t\t\t\t\t<div className=\"flex flex-wrap gap-4\">\n\t\t\t\t\t\t<KolButton\n\t\t\t\t\t\t\t_label=\"with inline icons\"\n\t\t\t\t\t\t\t_icons={{\n\t\t\t\t\t\t\t\tleft: 'kolicon-cogwheel',\n\t\t\t\t\t\t\t\tright: 'kolicon-cogwheel',\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t_shortKey=\"n\"\n\t\t\t\t\t\t\t_on={dummyEventHandler}\n\t\t\t\t\t\t/>\n\t\t\t\t\t</div>\n\t\t\t\t</SampleBlock>\n\n\t\t\t\t<p>\n\t\t\t\t\tThis button wires the announced short key up manually: a <code>keydown</code> listener triggers the same action as a click. Press <kbd>Alt</kbd> +{' '}\n\t\t\t\t\t<kbd>M</kbd> (or click the button) to open the toast.\n\t\t\t\t</p>\n\t\t\t\t<div className=\"flex flex-wrap gap-4\">\n\t\t\t\t\t<KolButton _label=\"With working M short key\" _shortKey={interactiveShortKey} _on={dummyEventHandler} />\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</>\n\t);\n};\n",
|
|
721
729
|
"kind": "sample"
|
|
722
730
|
},
|
|
723
731
|
{
|
|
@@ -725,7 +733,7 @@
|
|
|
725
733
|
"group": "button",
|
|
726
734
|
"name": "spinner",
|
|
727
735
|
"path": "packages/samples/react/src/components/button/spinner.tsx",
|
|
728
|
-
"code": "import { KolButton } from '@public-ui/react-v19';\nimport type { FC } from 'react';\nimport React from 'react';\nimport {
|
|
736
|
+
"code": "import { KolButton } from '@public-ui/react-v19';\nimport type { FC } from 'react';\nimport React from 'react';\nimport { useAlert } from '../../hooks/useAlert';\nimport { SampleBlock } from '../SampleBlock';\nimport { SampleDescription } from '../SampleDescription';\n\nexport const ButtonSpinner: FC = () => {\n\tconst { dummyClickEventHandler } = useAlert();\n\n\tconst dummyEventHandler = {\n\t\tonClick: dummyClickEventHandler,\n\t};\n\n\treturn (\n\t\t<>\n\t\t\t<SampleDescription>\n\t\t\t\t<p>\n\t\t\t\t\tThis story demonstrates icon-only buttons with an animated spinning loader icon. The animation is applied using CSS parts to target the icon element\n\t\t\t\t\tdirectly.\n\t\t\t\t</p>\n\t\t\t</SampleDescription>\n\n\t\t\t<div className=\"grid gap-8\">\n\t\t\t\t<SampleBlock id=\"animated-spinner-icon-css-part\" heading=\"Animated Spinner Icon via CSS Part\" fitContent>\n\t\t\t\t\t<div className=\"flex flex-wrap gap-4\">\n\t\t\t\t\t\t<KolButton\n\t\t\t\t\t\t\tclassName=\"spinner-button\"\n\t\t\t\t\t\t\t_hideLabel\n\t\t\t\t\t\t\t_icons={{\n\t\t\t\t\t\t\t\tleft: 'kolicon-cogwheel',\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t_label=\"Loading\"\n\t\t\t\t\t\t\t_variant=\"primary\"\n\t\t\t\t\t\t\t_on={dummyEventHandler}\n\t\t\t\t\t\t/>\n\t\t\t\t\t\t<KolButton\n\t\t\t\t\t\t\tclassName=\"spinner-button spinner-slow\"\n\t\t\t\t\t\t\t_hideLabel\n\t\t\t\t\t\t\t_icons={{\n\t\t\t\t\t\t\t\tleft: 'kolicon-cogwheel',\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t_label=\"Syncing\"\n\t\t\t\t\t\t\t_variant=\"secondary\"\n\t\t\t\t\t\t\t_on={dummyEventHandler}\n\t\t\t\t\t\t/>\n\t\t\t\t\t\t<KolButton\n\t\t\t\t\t\t\tclassName=\"spinner-button spinner-slower\"\n\t\t\t\t\t\t\t_hideLabel\n\t\t\t\t\t\t\t_icons={{\n\t\t\t\t\t\t\t\tleft: 'kolicon-cogwheel',\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t_label=\"Processing\"\n\t\t\t\t\t\t\t_variant=\"tertiary\"\n\t\t\t\t\t\t\t_on={dummyEventHandler}\n\t\t\t\t\t\t/>\n\t\t\t\t\t</div>\n\t\t\t\t</SampleBlock>\n\n\t\t\t\t<SampleBlock id=\"spinner-label\" heading=\"Spinner with Label\" fitContent>\n\t\t\t\t\t<div className=\"flex flex-wrap gap-4\">\n\t\t\t\t\t\t<KolButton\n\t\t\t\t\t\t\tclassName=\"spinner-button\"\n\t\t\t\t\t\t\t_icons={{\n\t\t\t\t\t\t\t\tleft: 'kolicon-cogwheel',\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t_label=\"Loading...\"\n\t\t\t\t\t\t\t_variant=\"primary\"\n\t\t\t\t\t\t\t_on={dummyEventHandler}\n\t\t\t\t\t\t/>\n\t\t\t\t\t\t<KolButton\n\t\t\t\t\t\t\tclassName=\"spinner-button\"\n\t\t\t\t\t\t\t_icons={{\n\t\t\t\t\t\t\t\tleft: 'kolicon-cogwheel',\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t_label=\"Syncing...\"\n\t\t\t\t\t\t\t_variant=\"secondary\"\n\t\t\t\t\t\t\t_on={dummyEventHandler}\n\t\t\t\t\t\t/>\n\t\t\t\t\t</div>\n\t\t\t\t</SampleBlock>\n\t\t\t</div>\n\n\t\t\t<style>\n\t\t\t\t{`\n\t\t\t\t\t@keyframes spin {\n\t\t\t\t\t\tfrom {\n\t\t\t\t\t\t\ttransform: rotate(0deg);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tto {\n\t\t\t\t\t\t\ttransform: rotate(360deg);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t/* Target the icon part inside the button */\n\t\t\t\t\t.spinner-button::part(icon) {\n\t\t\t\t\t\tanimation: spin 1s linear infinite;\n\t\t\t\t\t}\n\n\t\t\t\t\t.spinner-slow::part(icon) {\n\t\t\t\t\t\tanimation-duration: 1.5s;\n\t\t\t\t\t}\n\n\t\t\t\t\t.spinner-slower::part(icon) {\n\t\t\t\t\t\tanimation-duration: 2s;\n\t\t\t\t\t}\n\n\t\t\t\t\t@media (prefers-reduced-motion) {\n\t\t\t\t\t\t.spinner-button::part(icon){\n\t\t\t\t\t\t\tanimation-duration: 10s;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t`}\n\t\t\t</style>\n\t\t</>\n\t);\n};\n",
|
|
729
737
|
"kind": "sample"
|
|
730
738
|
},
|
|
731
739
|
{
|
|
@@ -733,7 +741,7 @@
|
|
|
733
741
|
"group": "button",
|
|
734
742
|
"name": "variants",
|
|
735
743
|
"path": "packages/samples/react/src/components/button/variants.tsx",
|
|
736
|
-
"code": "import { KolButton } from '@public-ui/react-v19';\nimport type { FC } from 'react';\nimport React, { useMemo } from 'react';\nimport { useSearchParams } from 'react-router';\nimport {
|
|
744
|
+
"code": "import { KolButton } from '@public-ui/react-v19';\nimport type { FC } from 'react';\nimport React, { useMemo } from 'react';\nimport { useSearchParams } from 'react-router';\nimport { useAlert } from '../../hooks/useAlert';\nimport { fetchVariantData } from '../../shares/fetchVariantData';\nimport { getTheme } from '../../shares/store';\nimport { SampleBlock } from '../SampleBlock';\nimport { SampleDescription } from '../SampleDescription';\n\nexport const ButtonVariants: FC = () => {\n\tconst [searchParams] = useSearchParams();\n\tconst theme = searchParams.get('theme') ?? getTheme();\n\tconst data = useMemo(() => (theme ? fetchVariantData(theme, 'buttonVariants') : []), [theme]);\n\n\tconst { dummyClickEventHandler } = useAlert();\n\n\tconst dummyEventHandler = {\n\t\tonClick: dummyClickEventHandler,\n\t};\n\n\treturn (\n\t\t<>\n\t\t\t<SampleDescription>\n\t\t\t\t<p>\n\t\t\t\t\tThis story showcases all available button variants for this theme. You can import <code>ButtonVariantsEnum</code> from your theme to always use the\n\t\t\t\t\tright variants.\n\t\t\t\t</p>\n\t\t\t</SampleDescription>\n\n\t\t\t<div className=\"grid gap-8\">\n\t\t\t\t<SampleBlock id=\"variants\" heading=\"All theme exclusive button variants\" fitContent>\n\t\t\t\t\t<div className=\"flex flex-wrap gap-4 items-center\">\n\t\t\t\t\t\t{!Array.isArray(data) || data.length === 0 ? (\n\t\t\t\t\t\t\t<p>This theme has no variants for this component.</p>\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\tdata.map((element) => {\n\t\t\t\t\t\t\t\treturn <KolButton _icons=\"kolicon-house\" _label={`${element}`} _variant={element} key={element} _on={dummyEventHandler} />;\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t)}\n\t\t\t\t\t</div>\n\t\t\t\t\t<div className=\"flex flex-wrap gap-4 items-center\">\n\t\t\t\t\t\t{!Array.isArray(data) || data.length === 0 ? (\n\t\t\t\t\t\t\t<p>This theme has no variants for this component.</p>\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\tdata.map((element) => {\n\t\t\t\t\t\t\t\treturn <KolButton _hideLabel _icons=\"kolicon-settings\" _label={`${element}`} _variant={element} key={element} _on={dummyEventHandler} />;\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t)}\n\t\t\t\t\t</div>\n\t\t\t\t</SampleBlock>\n\t\t\t</div>\n\t\t</>\n\t);\n};\n",
|
|
737
745
|
"kind": "sample"
|
|
738
746
|
},
|
|
739
747
|
{
|
|
@@ -741,7 +749,7 @@
|
|
|
741
749
|
"group": "button",
|
|
742
750
|
"name": "width",
|
|
743
751
|
"path": "packages/samples/react/src/components/button/width.tsx",
|
|
744
|
-
"code": "import { KolButton } from '@public-ui/react-v19';\nimport type { FC } from 'react';\nimport React from 'react';\nimport {
|
|
752
|
+
"code": "import { KolButton } from '@public-ui/react-v19';\nimport type { FC } from 'react';\nimport React from 'react';\nimport { useAlert } from '../../hooks/useAlert';\nimport { SampleBlock } from '../SampleBlock';\nimport { SampleDescription } from '../SampleDescription';\n\nexport const ButtonWidth: FC = () => {\n\tconst { dummyClickEventHandler } = useAlert();\n\n\tconst ARGS = {\n\t\tclassName: 'w-8rem',\n\t\t_on: {\n\t\t\tonClick: dummyClickEventHandler,\n\t\t},\n\t};\n\n\treturn (\n\t\t<>\n\t\t\t<SampleDescription>\n\t\t\t\t<p>This story demonstrates buttons with custom widths. You can control the button width using CSS classes.</p>\n\t\t\t</SampleDescription>\n\n\t\t\t<div className=\"grid gap-8\">\n\t\t\t\t<SampleBlock id=\"fixed-width-buttons-8rem\" heading=\"Fixed Width Buttons (8rem)\" fitContent>\n\t\t\t\t\t<div className=\"flex flex-wrap gap-4\">\n\t\t\t\t\t\t<KolButton _label=\"Primary\" _variant=\"primary\" {...ARGS} />\n\t\t\t\t\t\t<KolButton _label=\"Secondary\" _variant=\"secondary\" {...ARGS} />\n\t\t\t\t\t\t<KolButton _label=\"Normal\" _variant=\"normal\" {...ARGS} />\n\t\t\t\t\t\t<KolButton _label=\"Danger\" _variant=\"danger\" {...ARGS} />\n\t\t\t\t\t\t<KolButton _label=\"Ghost\" _variant=\"ghost\" {...ARGS} />\n\t\t\t\t\t</div>\n\t\t\t\t</SampleBlock>\n\n\t\t\t\t<SampleBlock id=\"fixed-width-disabled-buttons\" heading=\"Fixed Width Disabled Buttons (8rem)\" fitContent>\n\t\t\t\t\t<div className=\"flex flex-wrap gap-4\">\n\t\t\t\t\t\t<KolButton _disabled _label=\"Primary\" _variant=\"primary\" {...ARGS} />\n\t\t\t\t\t\t<KolButton _disabled _label=\"Secondary\" _variant=\"secondary\" {...ARGS} />\n\t\t\t\t\t\t<KolButton _disabled _label=\"Normal\" _variant=\"normal\" {...ARGS} />\n\t\t\t\t\t\t<KolButton _disabled _label=\"Danger\" _variant=\"danger\" {...ARGS} />\n\t\t\t\t\t\t<KolButton _disabled _label=\"Ghost\" _variant=\"ghost\" {...ARGS} />\n\t\t\t\t\t</div>\n\t\t\t\t</SampleBlock>\n\t\t\t</div>\n\t\t</>\n\t);\n};\n",
|
|
745
753
|
"kind": "sample"
|
|
746
754
|
},
|
|
747
755
|
{
|
|
@@ -885,7 +893,7 @@
|
|
|
885
893
|
"group": "handout",
|
|
886
894
|
"name": "basic",
|
|
887
895
|
"path": "packages/samples/react/src/components/handout/basic.tsx",
|
|
888
|
-
"code": "import type { KoliBriTableCell, KoliBriTableHeaders } from '@public-ui/components';\nimport {\n\tKolAbbr,\n\tKolAccordion,\n\tKolAlert,\n\tKolBadge,\n\tKolBreadcrumb,\n\tKolButton,\n\tKolButtonLink,\n\tKolCard,\n\tKolDetails,\n\tKolForm,\n\tKolHeading,\n\tKolInputCheckbox,\n\tKolInputColor,\n\tKolInputDate,\n\tKolInputEmail,\n\tKolInputFile,\n\tKolInputNumber,\n\tKolInputPassword,\n\tKolInputRadio,\n\tKolInputRange,\n\tKolInputText,\n\tKolKolibri,\n\tKolLink,\n\tKolLinkButton,\n\tKolNav,\n\tKolProgress,\n\tKolSelect,\n\tKolTableStateful,\n\tKolTabs,\n\tKolTextarea,\n\tKolVersion,\n} from '@public-ui/react-v19';\nimport type { ComponentProps, FC } from 'react';\nimport React from 'react';\n\nimport { useToasterService } from '../../hooks/useToasterService';\nimport { getRoot } from '../../shares/react-roots';\nimport { getTheme, getThemeName } from '../../shares/store';\nimport { TABLE_DATA, type TableDataType } from './table-data';\n\ntype KolButtonProps = ComponentProps<typeof KolButton>;\n\nfunction KolButtonWrapper(props: KolButtonProps & { style: Record<string, unknown> }) {\n\tconst { dummyClickEventHandler } = useToasterService();\n\tconst dummyEventHandler = {\n\t\tonClick: dummyClickEventHandler,\n\t};\n\treturn <KolButton {...props} _on={dummyEventHandler} />;\n}\n\nconst TABLE_HEADERS: KoliBriTableHeaders = {\n\thorizontal: [\n\t\t[\n\t\t\t{\n\t\t\t\tlabel: 'Workdays',\n\t\t\t\tcolSpan: 5,\n\t\t\t\twidth: 500,\n\t\t\t},\n\t\t\t{\n\t\t\t\tlabel: 'Weekend',\n\t\t\t\tcolSpan: 2,\n\t\t\t\twidth: 200,\n\t\t\t},\n\t\t],\n\t\t[\n\t\t\t{\n\t\t\t\tkey: 'monday',\n\t\t\t\tlabel: 'Monday',\n\t\t\t\trender: (el: HTMLElement, cell: KoliBriTableCell) => {\n\t\t\t\t\tconst { label } = cell as { label: string };\n\t\t\t\t\trenderCellContent(el, <KolButtonWrapper _label={label} style={{ fontSize: '75%' }} />);\n\t\t\t\t},\n\t\t\t\tcompareFn: (first, second) => {\n\t\t\t\t\tif ((first as TableDataType).monday < (second as TableDataType).monday) {\n\t\t\t\t\t\treturn -1;\n\t\t\t\t\t}\n\t\t\t\t\tif ((first as TableDataType).monday > (second as TableDataType).monday) {\n\t\t\t\t\t\treturn 1;\n\t\t\t\t\t}\n\t\t\t\t\treturn 0;\n\t\t\t\t},\n\t\t\t\tsortDirection: 'ASC',\n\t\t\t\ttextAlign: 'right',\n\t\t\t\twidth: 100,\n\t\t\t},\n\t\t\t{\n\t\t\t\tkey: 'tuesday',\n\t\t\t\tlabel: 'Tuesday',\n\t\t\t\trender: (el: HTMLElement, cell: KoliBriTableCell) => {\n\t\t\t\t\tconst { label } = cell as { label: string };\n\t\t\t\t\trenderCellContent(el, <KolBadge _color=\"#060\" _label={label}></KolBadge>);\n\t\t\t\t},\n\t\t\t\tcompareFn: (first, second) => {\n\t\t\t\t\tif ((first as TableDataType).tuesday < (second as TableDataType).tuesday) {\n\t\t\t\t\t\treturn -1;\n\t\t\t\t\t}\n\t\t\t\t\tif ((first as TableDataType).tuesday > (second as TableDataType).tuesday) {\n\t\t\t\t\t\treturn 1;\n\t\t\t\t\t}\n\t\t\t\t\treturn 0;\n\t\t\t\t},\n\t\t\t\tsortDirection: 'DESC',\n\t\t\t\twidth: 100,\n\t\t\t},\n\t\t\t{\n\t\t\t\tkey: 'wednesday',\n\t\t\t\tlabel: 'Wednesday',\n\t\t\t\trender: (el: HTMLElement, cell: KoliBriTableCell) => {\n\t\t\t\t\tconst { label } = cell as { label: string };\n\t\t\t\t\trenderCellContent(el, <KolBadge _color=\"#006\" _label={label}></KolBadge>);\n\t\t\t\t},\n\t\t\t\twidth: 110,\n\t\t\t},\n\t\t\t{\n\t\t\t\tkey: 'thursday',\n\t\t\t\tlabel: 'Thursday',\n\t\t\t\trender: (el: HTMLElement, cell: KoliBriTableCell) => {\n\t\t\t\t\tconst { label } = cell as { label: string };\n\t\t\t\t\trenderCellContent(el, <KolBadge _color=\"#600\" _label={label}></KolBadge>);\n\t\t\t\t},\n\t\t\t\twidth: 100,\n\t\t\t},\n\t\t\t{\n\t\t\t\tkey: 'friday',\n\t\t\t\tlabel: 'Friday',\n\t\t\t\trender: (el: HTMLElement, cell: KoliBriTableCell) => {\n\t\t\t\t\tconst { label } = cell as { label: string };\n\t\t\t\t\trenderCellContent(el, <KolBadge _color=\"#303\" _label={label}></KolBadge>);\n\t\t\t\t},\n\t\t\t\twidth: 100,\n\t\t\t},\n\t\t\t{\n\t\t\t\tkey: 'saturday',\n\t\t\t\tlabel: 'Saturday',\n\t\t\t\trender: (el: HTMLElement, cell: KoliBriTableCell) => {\n\t\t\t\t\tconst { label } = cell as { label: string };\n\t\t\t\t\trenderCellContent(el, <KolBadge _color=\"#330\" _label={label}></KolBadge>);\n\t\t\t\t},\n\t\t\t\twidth: 100,\n\t\t\t},\n\t\t\t{\n\t\t\t\tkey: 'sunday',\n\t\t\t\tlabel: 'Sunday',\n\t\t\t\trender: (el: HTMLElement, cell: KoliBriTableCell) => {\n\t\t\t\t\tconst { label } = cell as { label: string };\n\t\t\t\t\trenderCellContent(el, <KolBadge _color=\"#033\" _label={label}></KolBadge>);\n\t\t\t\t},\n\t\t\t\twidth: 100,\n\t\t\t},\n\t\t],\n\t],\n\tvertical: [\n\t\t[\n\t\t\t{\n\t\t\t\tlabel: 'Early',\n\t\t\t\twidth: 100,\n\t\t\t},\n\t\t\t{\n\t\t\t\tlabel: 'Noon',\n\t\t\t\twidth: 100,\n\t\t\t},\n\t\t\t{\n\t\t\t\tlabel: 'Evening',\n\t\t\t\twidth: 100,\n\t\t\t},\n\t\t\t{\n\t\t\t\tlabel: 'Night',\n\t\t\t\twidth: 100,\n\t\t\t},\n\t\t],\n\t],\n};\n\nconst renderCellContent = (element: HTMLElement, content: React.ReactNode) => {\n\tconst renderElement = document.createElement('div');\n\trenderElement.setAttribute('role', 'presentation');\n\telement.innerHTML = '';\n\telement.appendChild(renderElement);\n\tgetRoot(renderElement).render(content);\n};\n\nexport const HandoutBasic: FC = () => {\n\tconst { dummyClickEventHandler } = useToasterService();\n\n\tconst dummyEventHandler = {\n\t\tonClick: dummyClickEventHandler,\n\t};\n\n\treturn (\n\t\t<div className=\"grid gap-4\">\n\t\t\t<div className=\"grid gap-4 md:grid-cols-[auto_1fr_1fr] items-center\">\n\t\t\t\t<KolKolibri className=\"block w-75px\" _labeled={false}></KolKolibri>\n\t\t\t\t<KolHeading _label=\"\" _level={1}>\n\t\t\t\t\t<span slot=\"expert\">\n\t\t\t\t\t\tKolibri-Handout <small>for {getThemeName(getTheme())}</small>\n\t\t\t\t\t</span>\n\t\t\t\t</KolHeading>\n\t\t\t\t<KolDetails _label=\"Abstract\" _open>\n\t\t\t\t\tThe handout shows a selection of KoliBri components in the style of <strong>{getThemeName(getTheme())}</strong>. Since KoliBri offers self-contained,\n\t\t\t\t\taccessible web components that can be customized to your own corporate design using theming, you don't have to develop these components yourself.\n\t\t\t\t\tFor more information read our documentation and follow us (\n\t\t\t\t\t<KolLink _label=\"https://github.com/public-ui/kolibri\" _href=\"https://github.com/public-ui/kolibri\" _target=\"_blank\" />\n\t\t\t\t\t).\n\t\t\t\t</KolDetails>\n\t\t\t</div>\n\t\t\t<div className=\"grid gap-4 sm:grid-cols-6 md:grid-cols-6 xl:grid-cols-12\">\n\t\t\t\t<KolCard className=\"col-span-6 sm:col-span-6 md:col-span-3 xl:col-span-2\" _label=\"Heading\" _level={2}>\n\t\t\t\t\t<div slot=\"\" className=\"grid gap-2 p-2\">\n\t\t\t\t\t\t<KolHeading _label=\"Heading Level 1\" _level={1}></KolHeading>\n\t\t\t\t\t\t<KolHeading _label=\"Heading Level 2\" _level={2}></KolHeading>\n\t\t\t\t\t\t<KolHeading _label=\"Heading Level 3\" _level={3}></KolHeading>\n\t\t\t\t\t\t<KolHeading _label=\"Heading Level 4\" _level={4}></KolHeading>\n\t\t\t\t\t\t<KolHeading _label=\"Heading Level 5\" _level={5}></KolHeading>\n\t\t\t\t\t\t<KolHeading _label=\"Heading Level 6\" _level={6}></KolHeading>\n\t\t\t\t\t\t<KolHeading _label=\"Heading Level 6\" _secondaryHeadline=\"Lessons\" _level={6}></KolHeading>\n\t\t\t\t\t</div>\n\t\t\t\t</KolCard>\n\t\t\t\t{/* <KolCard className=\"col-span-3\" _label=\"Accordion\" _level={2}>\n\t\t\t\t<div slot=\"\" className=\"grid gap-2 p-2\">\n\t\t\t\t\t<KolAccordion _label=\"Überschrift Level 1\" _level={1} _open>\n\t\t\t\t\t\t<div slot=\"\">Inhalt Accordion Tab 1</div>\n\t\t\t\t\t</KolAccordion>\n\t\t\t\t\t<KolAccordion _label=\"Überschrift Level 2\" _level={2}>\n\t\t\t\t\t\t<div slot=\"\">Inhalt Accordion Tab 2</div>\n\t\t\t\t\t</KolAccordion>\n\t\t\t\t\t<KolAccordion _label=\"Überschrift Level 3\" _level={3}>\n\t\t\t\t\t\t<div slot=\"\">Inhalt Accordion Tab 3</div>\n\t\t\t\t\t</KolAccordion>\n\t\t\t\t\t<KolAccordion _label=\"Überschrift Level 4\" _level={4}>\n\t\t\t\t\t\t<div slot=\"\">Inhalt Accordion Tab 4</div>\n\t\t\t\t\t</KolAccordion>\n\t\t\t\t\t<KolAccordion _label=\"Überschrift Level 5\" _level={5}>\n\t\t\t\t\t\t<div slot=\"\">Inhalt Accordion Tab 5</div>\n\t\t\t\t\t</KolAccordion>\n\t\t\t\t\t<KolAccordion _label=\"Überschrift Level 6\" _level={6}>\n\t\t\t\t\t\t<div slot=\"\">Inhalt Accordion Tab 6</div>\n\t\t\t\t\t</KolAccordion>\n\t\t\t\t</div>\n\t\t\t</KolCard> */}\n\t\t\t\t<KolCard className=\"col-span-6 sm:col-span-6 md:col-span-3 xl:col-span-2\" _label=\"Abbreviation and Progress\" _level={2}>\n\t\t\t\t\t<div slot=\"\" className=\"grid gap-2 p-2\">\n\t\t\t\t\t\t<p>\n\t\t\t\t\t\t\tI am <KolAbbr>e.g.</KolAbbr> an abbreviation.\n\t\t\t\t\t\t</p>\n\t\t\t\t\t\t<KolProgress _variant=\"bar\" _max={100} _value={33} _label=\"Progress\" />\n\t\t\t\t\t\t<KolProgress _variant=\"cycle\" _max={100} _value={66} _label=\"Progress\" />\n\t\t\t\t\t</div>\n\t\t\t\t</KolCard>\n\t\t\t\t<KolCard className=\"col-span-6 sm:col-span-6 md:col-span-6 xl:col-span-3\" _label=\"Button, LinkButton and Tab\" _level={2}>\n\t\t\t\t\t<div slot=\"\" className=\"grid gap-2 p-2\">\n\t\t\t\t\t\t<KolTabs _label=\"\" _selected={0} _tabs={[{ _label: 'Button' }, { _label: 'LinkButton' }, { _label: 'Disabled Tab', _disabled: true }]}>\n\t\t\t\t\t\t\t<div className=\"grid gap-2 py-2\">\n\t\t\t\t\t\t\t\t<div className=\"grid gap-2 grid-cols-[4fr_4fr_1fr] justify-items-center\">\n\t\t\t\t\t\t\t\t\t<KolButton _icons={{ left: 'kolicon-chevron-left' }} _label=\"primary\" _variant=\"primary\" _on={dummyEventHandler}></KolButton>\n\t\t\t\t\t\t\t\t\t<KolButton _disabled _icons={{ left: 'kolicon-chevron-left' }} _label=\"primary\" _variant=\"primary\" _on={dummyEventHandler}></KolButton>\n\t\t\t\t\t\t\t\t\t<KolButton _hideLabel _icons=\"kolicon-chevron-left\" _label=\"primary\" _variant=\"primary\" _on={dummyEventHandler}></KolButton>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div className=\"grid gap-2 grid-cols-[4fr_4fr_1fr] justify-items-center\">\n\t\t\t\t\t\t\t\t\t<KolButton _icons={{ right: 'kolicon-chevron-right' }} _label=\"secondary\" _variant=\"secondary\" _on={dummyEventHandler}></KolButton>\n\t\t\t\t\t\t\t\t\t<KolButton _disabled _icons={{ right: 'kolicon-chevron-right' }} _label=\"secondary\" _variant=\"secondary\" _on={dummyEventHandler}></KolButton>\n\t\t\t\t\t\t\t\t\t<KolButton _hideLabel _icons=\"kolicon-chevron-right\" _label=\"secondary\" _variant=\"secondary\" _on={dummyEventHandler}></KolButton>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div className=\"grid gap-2 grid-cols-[4fr_4fr_1fr] justify-items-center\">\n\t\t\t\t\t\t\t\t\t<KolButton _icons={{ top: 'kolicon-chevron-up' }} _label=\"danger\" _variant=\"danger\" _on={dummyEventHandler}></KolButton>\n\t\t\t\t\t\t\t\t\t<KolButton _disabled _icons={{ top: 'kolicon-chevron-up' }} _label=\"danger\" _variant=\"danger\" _on={dummyEventHandler}></KolButton>\n\t\t\t\t\t\t\t\t\t<KolButton _hideLabel _icons=\"kolicon-chevron-up\" _label=\"danger\" _variant=\"danger\" _on={dummyEventHandler}></KolButton>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div className=\"grid gap-2 grid-cols-[4fr_4fr_1fr] justify-items-center\">\n\t\t\t\t\t\t\t\t\t<KolButton _icons={{ bottom: 'kolicon-chevron-down' }} _label=\"normal\" _variant=\"normal\" _on={dummyEventHandler}></KolButton>\n\t\t\t\t\t\t\t\t\t<KolButton _disabled _icons={{ bottom: 'kolicon-chevron-down' }} _label=\"normal\" _variant=\"normal\" _on={dummyEventHandler}></KolButton>\n\t\t\t\t\t\t\t\t\t<KolButton _hideLabel _icons=\"kolicon-chevron-down\" _label=\"normal\" _variant=\"normal\" _on={dummyEventHandler}></KolButton>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div className=\"grid gap-2 grid-cols-[4fr_4fr_1fr] justify-items-center\">\n\t\t\t\t\t\t\t\t\t<KolButton _label=\"ghost\" _variant=\"ghost\"></KolButton>\n\t\t\t\t\t\t\t\t\t<KolButton _disabled _label=\"ghost\" _variant=\"ghost\"></KolButton>\n\t\t\t\t\t\t\t\t\t<KolButton _icons=\"kolicon-house\" _hideLabel _label=\"ghost\" _variant=\"ghost\" _on={dummyEventHandler}></KolButton>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<div className=\"grid gap-2 py-2\">\n\t\t\t\t\t\t\t\t<div className=\"grid gap-2 grid-cols-[4fr_4fr_1fr] justify-items-center\">\n\t\t\t\t\t\t\t\t\t<KolLinkButton _href=\"#/back-page\" _icons={{ left: 'kolicon-chevron-left' }} _label=\"primary\" _variant=\"primary\"></KolLinkButton>\n\t\t\t\t\t\t\t\t\t<KolLinkButton _href=\"#/back-page\" _icons={{ left: 'kolicon-chevron-left' }} _label=\"primary\" _variant=\"primary\"></KolLinkButton>\n\t\t\t\t\t\t\t\t\t<KolLinkButton _href=\"#/back-page\" _hideLabel _icons=\"kolicon-chevron-left\" _label=\"primary\" _variant=\"primary\"></KolLinkButton>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div className=\"grid gap-2 grid-cols-[4fr_4fr_1fr] justify-items-center\">\n\t\t\t\t\t\t\t\t\t<KolLinkButton _href=\"#/back-page\" _icons={{ right: 'kolicon-chevron-right' }} _label=\"secondary\" _variant=\"secondary\"></KolLinkButton>\n\t\t\t\t\t\t\t\t\t<KolLinkButton _href=\"#/back-page\" _icons={{ right: 'kolicon-chevron-right' }} _label=\"secondary\" _variant=\"secondary\"></KolLinkButton>\n\t\t\t\t\t\t\t\t\t<KolLinkButton _href=\"#/back-page\" _hideLabel _icons=\"kolicon-chevron-right\" _label=\"secondary\" _variant=\"secondary\"></KolLinkButton>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div className=\"grid gap-2 grid-cols-[4fr_4fr_1fr] justify-items-center\">\n\t\t\t\t\t\t\t\t\t<KolLinkButton _href=\"#/back-page\" _icons={{ top: 'kolicon-chevron-up' }} _label=\"danger\" _variant=\"danger\"></KolLinkButton>\n\t\t\t\t\t\t\t\t\t<KolLinkButton _href=\"#/back-page\" _icons={{ top: 'kolicon-chevron-up' }} _label=\"danger\" _variant=\"danger\"></KolLinkButton>\n\t\t\t\t\t\t\t\t\t<KolLinkButton _href=\"#/back-page\" _hideLabel _icons=\"kolicon-chevron-up\" _label=\"danger\" _variant=\"danger\"></KolLinkButton>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div className=\"grid gap-2 grid-cols-[4fr_4fr_1fr] justify-items-center\">\n\t\t\t\t\t\t\t\t\t<KolLinkButton _href=\"#/back-page\" _icons={{ bottom: 'kolicon-chevron-down' }} _label=\"normal\" _variant=\"normal\"></KolLinkButton>\n\t\t\t\t\t\t\t\t\t<KolLinkButton _href=\"#/back-page\" _icons={{ bottom: 'kolicon-chevron-down' }} _label=\"normal\" _variant=\"normal\"></KolLinkButton>\n\t\t\t\t\t\t\t\t\t<KolLinkButton _href=\"#/back-page\" _hideLabel _icons=\"kolicon-chevron-down\" _label=\"normal\" _variant=\"normal\"></KolLinkButton>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div className=\"grid gap-2 grid-cols-[4fr_4fr_1fr] justify-items-center\">\n\t\t\t\t\t\t\t\t\t<KolLinkButton _href=\"#/back-page\" _label=\"ghost\" _variant=\"ghost\"></KolLinkButton>\n\t\t\t\t\t\t\t\t\t<KolLinkButton _href=\"#/back-page\" _label=\"ghost\" _variant=\"ghost\"></KolLinkButton>\n\t\t\t\t\t\t\t\t\t<KolLinkButton _href=\"#/back-page\" _icons=\"kolicon-house\" _hideLabel _label=\"ghost\" _variant=\"ghost\"></KolLinkButton>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</KolTabs>\n\t\t\t\t\t</div>\n\t\t\t\t</KolCard>\n\t\t\t\t<KolCard className=\"col-span-6 sm:col-span-6 md:col-span-2 xl:col-span-2\" _label=\"Accordion, Link and ButtonLink\" _level={2}>\n\t\t\t\t\t<div slot=\"\" className=\"grid gap-2 p-2\">\n\t\t\t\t\t\t<KolAccordion _label=\"Links\" _level={3} _open>\n\t\t\t\t\t\t\t<div className=\"grid gap-2\" slot=\"\">\n\t\t\t\t\t\t\t\t<KolLink _href=\"#/back-page\" _label=\"Link text\"></KolLink>\n\t\t\t\t\t\t\t\t<KolLink _href=\"#/back-page\" _icons=\"kolicon-house\" _label=\"Link text with icon\"></KolLink>\n\t\t\t\t\t\t\t\t<KolLink _href=\"#/back-page\" _icons=\"kolicon-house\" _hideLabel _label=\"Link text with icon only\"></KolLink>\n\t\t\t\t\t\t\t\t<KolLink _href=\"/\" _label=\"Visited link\"></KolLink>\n\t\t\t\t\t\t\t\t<p>\n\t\t\t\t\t\t\t\t\tI am a <KolLink _href=\"#/back-page\" _label=\"externer Link\" _target=\"w3c\"></KolLink> in the running text.\n\t\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</KolAccordion>\n\t\t\t\t\t\t<KolAccordion _label=\"ButtonLinks\" _level={3}>\n\t\t\t\t\t\t\t<div className=\"grid gap-2\" slot=\"\">\n\t\t\t\t\t\t\t\t<KolButtonLink _label=\"Link text\"></KolButtonLink>\n\t\t\t\t\t\t\t\t<KolButtonLink _icons=\"kolicon-house\" _label=\"Link text with icon\"></KolButtonLink>\n\t\t\t\t\t\t\t\t<KolButtonLink _icons=\"kolicon-house\" _hideLabel _label=\"Link text with icon only\"></KolButtonLink>\n\t\t\t\t\t\t\t\t<p>\n\t\t\t\t\t\t\t\t\tI am a <KolButtonLink _label=\"Link\"></KolButtonLink> in the running text.\n\t\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t\t\t<KolButtonLink\n\t\t\t\t\t\t\t\t\t_icons={{\n\t\t\t\t\t\t\t\t\t\tleft: 'kolicon-chevron-left',\n\t\t\t\t\t\t\t\t\t\tright: 'kolicon-chevron-right',\n\t\t\t\t\t\t\t\t\t\ttop: 'kolicon-chevron-up',\n\t\t\t\t\t\t\t\t\t\tbottom: 'kolicon-chevron-down',\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t_label=\"Icons\"\n\t\t\t\t\t\t\t\t></KolButtonLink>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</KolAccordion>\n\t\t\t\t\t</div>\n\t\t\t\t</KolCard>\n\t\t\t\t<KolCard className=\"col-span-6 sm:col-span-6 md:col-span-4 xl:col-span-3\" _label=\"Alert\" _level={2}>\n\t\t\t\t\t<div slot=\"\" className=\"grid gap-2 p-2\">\n\t\t\t\t\t\t<KolAlert _label=\"Default message\" _type=\"default\">\n\t\t\t\t\t\t\tThis is the text of the alert.\n\t\t\t\t\t\t</KolAlert>\n\t\t\t\t\t\t<KolAlert _type=\"success\">Success message text</KolAlert>\n\t\t\t\t\t\t<KolAlert _type=\"error\" _hasCloser>\n\t\t\t\t\t\t\tThis is a error message text.\n\t\t\t\t\t\t</KolAlert>\n\t\t\t\t\t\t<KolAlert _label=\"Info card\" _type=\"info\" _variant=\"card\">\n\t\t\t\t\t\t\tThis is the text of the alert.\n\t\t\t\t\t\t</KolAlert>\n\t\t\t\t\t\t<KolAlert _label=\"Warning card\" _type=\"warning\" _hasCloser _variant=\"card\">\n\t\t\t\t\t\t\tThis is the text of the alert.\n\t\t\t\t\t\t</KolAlert>\n\t\t\t\t\t</div>\n\t\t\t\t</KolCard>\n\t\t\t\t<KolCard className=\"col-span-6 sm:col-span-6 md:col-span-2 xl:col-span-2\" _label=\"Nav and Breadcrumb\" _level={2}>\n\t\t\t\t\t<div slot=\"\" className=\"grid gap-2 p-2\">\n\t\t\t\t\t\t<div>\n\t\t\t\t\t\t\t<KolNav\n\t\t\t\t\t\t\t\t_label=\"Main navigation\"\n\t\t\t\t\t\t\t\t_links={[\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t_label: 'Homepage',\n\t\t\t\t\t\t\t\t\t\t_icons: 'kolicon-house',\n\t\t\t\t\t\t\t\t\t\t_href: '#/back-page',\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t_label: '2 Navigation point',\n\t\t\t\t\t\t\t\t\t\t_icons: 'kolicon-house',\n\t\t\t\t\t\t\t\t\t\t_href: '#/back-page',\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t_active: true,\n\t\t\t\t\t\t\t\t\t\t_label: '3 Navigation point',\n\t\t\t\t\t\t\t\t\t\t_href: '#/back-page',\n\t\t\t\t\t\t\t\t\t\t_icons: 'kolicon-house',\n\t\t\t\t\t\t\t\t\t\t_children: [\n\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t_label: '3.1 Navigation point',\n\t\t\t\t\t\t\t\t\t\t\t\t_icons: 'kolicon-house',\n\t\t\t\t\t\t\t\t\t\t\t\t_href: '#/back-page',\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t_label: '3.2 External navigation point',\n\t\t\t\t\t\t\t\t\t\t\t\t_icons: 'kolicon-house',\n\t\t\t\t\t\t\t\t\t\t\t\t_href: '#/back-page',\n\t\t\t\t\t\t\t\t\t\t\t\t_target: '_blank',\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t_label: '3.3 Navigation point',\n\t\t\t\t\t\t\t\t\t\t\t\t_href: '#/back-page',\n\t\t\t\t\t\t\t\t\t\t\t\t_icons: 'kolicon-house',\n\t\t\t\t\t\t\t\t\t\t\t\t_children: [\n\t\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t_active: true,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t_label: '3.3.1 Navigation point (active)',\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t_icons: 'kolicon-house',\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t_href: '#/back-page',\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t{ _label: '3.3.2 Navigation point', _icons: 'kolicon-house', _href: '#/back-page' },\n\t\t\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t{ _label: '3 Navigation point', _icons: 'kolicon-house', _href: '#/back-page' },\n\t\t\t\t\t\t\t\t]}\n\t\t\t\t\t\t\t\t_hasCompactButton\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t{/* <KolSkipNav></KolSkipNav> */}\n\t\t\t\t\t\t<div>\n\t\t\t\t\t\t\t<KolBreadcrumb\n\t\t\t\t\t\t\t\t_label=\"Breadcrumb aus Text-Links\"\n\t\t\t\t\t\t\t\t_links={[\n\t\t\t\t\t\t\t\t\t{ _label: 'Homepage', _href: '#/back-page' },\n\t\t\t\t\t\t\t\t\t{ _label: 'Bottom of the homepage', _href: '#/back-page' },\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t_label: 'Underside of the underside',\n\t\t\t\t\t\t\t\t\t\t_href: '#/back-page',\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t]}\n\t\t\t\t\t\t\t></KolBreadcrumb>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t</KolCard>\n\t\t\t\t<KolCard className=\"col-span-6 sm:col-span-6 md:col-span-4 xl:col-span-5\" _label=\"Input\" _level={2}>\n\t\t\t\t\t<KolForm slot=\"\">\n\t\t\t\t\t\t<div className=\"grid gap-4 sm:grid-cols-2 md:grid-cols-3 p-2\">\n\t\t\t\t\t\t\t<KolInputColor _label={`Color`} />\n\t\t\t\t\t\t\t<KolInputFile _label={`Upload file`} />\n\t\t\t\t\t\t\t<KolInputNumber _label={`Number input`} />\n\t\t\t\t\t\t\t<KolInputDate _type=\"date\" _label={`Date`} />\n\t\t\t\t\t\t\t<KolInputEmail\n\t\t\t\t\t\t\t\t_icons=\"{'left': 'kolicon-house'}\"\n\t\t\t\t\t\t\t\t_msg={{ _type: 'error', _description: 'Test of an error message' }}\n\t\t\t\t\t\t\t\t_touched\n\t\t\t\t\t\t\t\t_label={`E-mail address`}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t<KolInputText _hint=\"I am a hint.\" _label={`First name`} />\n\t\t\t\t\t\t\t<KolInputPassword _label={`password`} />\n\t\t\t\t\t\t\t<KolSelect _options=\"[{'label':'Mr.','value':0},{'label':'Mrs.','value':1}]\" _label={`Stimmung`} />\n\t\t\t\t\t\t\t<KolInputRange _min={0} _max={50} _value={25} _label={`Slider`} />\n\t\t\t\t\t\t\t<KolInputRadio className=\"herr-frau\" _options=\"[{'label':'Mr.','value':0},{'label':'Mrs.','value':1}]\" _value=\"1\" _label={`Salutation`} />\n\t\t\t\t\t\t\t<div className=\"grid gap-4\">\n\t\t\t\t\t\t\t\t<KolInputRadio _orientation=\"horizontal\" _options=\"[{'label':'Mr.','value':0},{'label':'Mrs.','value':1}]\" _value=\"0\" _label={`Salutation`} />\n\t\t\t\t\t\t\t\t<KolInputCheckbox _label=\"\">\n\t\t\t\t\t\t\t\t\t<span slot=\"expert\">\n\t\t\t\t\t\t\t\t\t\tI accept the <KolAbbr>AGB</KolAbbr>.\n\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t</KolInputCheckbox>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<KolTextarea _rows={4} _label={`Textarea`} />\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</KolForm>\n\t\t\t\t</KolCard>\n\t\t\t\t<KolCard className=\"col-span-6 sm:col-span-6 md:col-span-4 xl:col-span-5\" _label=\"Table with Pagination\" _level={2}>\n\t\t\t\t\t<div slot=\"\" className=\"gap-2 p-2 flex flex-col\">\n\t\t\t\t\t\t<KolTableStateful _label=\"Table\" _headers={TABLE_HEADERS} _data={TABLE_DATA} _pagination></KolTableStateful>\n\t\t\t\t\t</div>\n\t\t\t\t</KolCard>\n\t\t\t</div>\n\t\t\t<KolVersion _label=\"5.0.2-test.2\"></KolVersion>\n\t\t\t{/* <KolImage _src=\"abgrenzung.jpg\" _alt=\"KoliBri Darstellung\"></KolImage> */}\n\t\t\t{/* <KolIndentedText></KolIndentedText> */}\n\t\t\t{/* <KolQuote></KolQuote> */}\n\t\t</div>\n\t);\n};\n",
|
|
896
|
+
"code": "import type { KoliBriTableCell, KoliBriTableHeaders } from '@public-ui/components';\nimport {\n\tKolAbbr,\n\tKolAccordion,\n\tKolAlert,\n\tKolBadge,\n\tKolBreadcrumb,\n\tKolButton,\n\tKolButtonLink,\n\tKolCard,\n\tKolDetails,\n\tKolForm,\n\tKolHeading,\n\tKolInputCheckbox,\n\tKolInputColor,\n\tKolInputDate,\n\tKolInputEmail,\n\tKolInputFile,\n\tKolInputNumber,\n\tKolInputPassword,\n\tKolInputRadio,\n\tKolInputRange,\n\tKolInputText,\n\tKolKolibri,\n\tKolLink,\n\tKolLinkButton,\n\tKolNav,\n\tKolProgress,\n\tKolSelect,\n\tKolTableStateful,\n\tKolTabs,\n\tKolTextarea,\n\tKolVersion,\n} from '@public-ui/react-v19';\nimport type { ComponentProps, FC } from 'react';\nimport React from 'react';\n\nimport { useAlert } from '../../hooks/useAlert';\nimport { getRoot } from '../../shares/react-roots';\nimport { getTheme, getThemeName } from '../../shares/store';\nimport { TABLE_DATA, type TableDataType } from './table-data';\n\ntype KolButtonProps = ComponentProps<typeof KolButton>;\n\nfunction KolButtonWrapper(props: KolButtonProps & { style: Record<string, unknown> }) {\n\tconst { dummyClickEventHandler } = useAlert();\n\tconst dummyEventHandler = {\n\t\tonClick: dummyClickEventHandler,\n\t};\n\treturn <KolButton {...props} _on={dummyEventHandler} />;\n}\n\nconst TABLE_HEADERS: KoliBriTableHeaders = {\n\thorizontal: [\n\t\t[\n\t\t\t{\n\t\t\t\tlabel: 'Workdays',\n\t\t\t\tcolSpan: 5,\n\t\t\t\twidth: 500,\n\t\t\t},\n\t\t\t{\n\t\t\t\tlabel: 'Weekend',\n\t\t\t\tcolSpan: 2,\n\t\t\t\twidth: 200,\n\t\t\t},\n\t\t],\n\t\t[\n\t\t\t{\n\t\t\t\tkey: 'monday',\n\t\t\t\tlabel: 'Monday',\n\t\t\t\trender: (el: HTMLElement, cell: KoliBriTableCell) => {\n\t\t\t\t\tconst { label } = cell as { label: string };\n\t\t\t\t\trenderCellContent(el, <KolButtonWrapper _label={label} style={{ fontSize: '75%' }} />);\n\t\t\t\t},\n\t\t\t\tcompareFn: (first, second) => {\n\t\t\t\t\tif ((first as TableDataType).monday < (second as TableDataType).monday) {\n\t\t\t\t\t\treturn -1;\n\t\t\t\t\t}\n\t\t\t\t\tif ((first as TableDataType).monday > (second as TableDataType).monday) {\n\t\t\t\t\t\treturn 1;\n\t\t\t\t\t}\n\t\t\t\t\treturn 0;\n\t\t\t\t},\n\t\t\t\tsortDirection: 'ASC',\n\t\t\t\ttextAlign: 'right',\n\t\t\t\twidth: 100,\n\t\t\t},\n\t\t\t{\n\t\t\t\tkey: 'tuesday',\n\t\t\t\tlabel: 'Tuesday',\n\t\t\t\trender: (el: HTMLElement, cell: KoliBriTableCell) => {\n\t\t\t\t\tconst { label } = cell as { label: string };\n\t\t\t\t\trenderCellContent(el, <KolBadge _color=\"#060\" _label={label}></KolBadge>);\n\t\t\t\t},\n\t\t\t\tcompareFn: (first, second) => {\n\t\t\t\t\tif ((first as TableDataType).tuesday < (second as TableDataType).tuesday) {\n\t\t\t\t\t\treturn -1;\n\t\t\t\t\t}\n\t\t\t\t\tif ((first as TableDataType).tuesday > (second as TableDataType).tuesday) {\n\t\t\t\t\t\treturn 1;\n\t\t\t\t\t}\n\t\t\t\t\treturn 0;\n\t\t\t\t},\n\t\t\t\tsortDirection: 'DESC',\n\t\t\t\twidth: 100,\n\t\t\t},\n\t\t\t{\n\t\t\t\tkey: 'wednesday',\n\t\t\t\tlabel: 'Wednesday',\n\t\t\t\trender: (el: HTMLElement, cell: KoliBriTableCell) => {\n\t\t\t\t\tconst { label } = cell as { label: string };\n\t\t\t\t\trenderCellContent(el, <KolBadge _color=\"#006\" _label={label}></KolBadge>);\n\t\t\t\t},\n\t\t\t\twidth: 110,\n\t\t\t},\n\t\t\t{\n\t\t\t\tkey: 'thursday',\n\t\t\t\tlabel: 'Thursday',\n\t\t\t\trender: (el: HTMLElement, cell: KoliBriTableCell) => {\n\t\t\t\t\tconst { label } = cell as { label: string };\n\t\t\t\t\trenderCellContent(el, <KolBadge _color=\"#600\" _label={label}></KolBadge>);\n\t\t\t\t},\n\t\t\t\twidth: 100,\n\t\t\t},\n\t\t\t{\n\t\t\t\tkey: 'friday',\n\t\t\t\tlabel: 'Friday',\n\t\t\t\trender: (el: HTMLElement, cell: KoliBriTableCell) => {\n\t\t\t\t\tconst { label } = cell as { label: string };\n\t\t\t\t\trenderCellContent(el, <KolBadge _color=\"#303\" _label={label}></KolBadge>);\n\t\t\t\t},\n\t\t\t\twidth: 100,\n\t\t\t},\n\t\t\t{\n\t\t\t\tkey: 'saturday',\n\t\t\t\tlabel: 'Saturday',\n\t\t\t\trender: (el: HTMLElement, cell: KoliBriTableCell) => {\n\t\t\t\t\tconst { label } = cell as { label: string };\n\t\t\t\t\trenderCellContent(el, <KolBadge _color=\"#330\" _label={label}></KolBadge>);\n\t\t\t\t},\n\t\t\t\twidth: 100,\n\t\t\t},\n\t\t\t{\n\t\t\t\tkey: 'sunday',\n\t\t\t\tlabel: 'Sunday',\n\t\t\t\trender: (el: HTMLElement, cell: KoliBriTableCell) => {\n\t\t\t\t\tconst { label } = cell as { label: string };\n\t\t\t\t\trenderCellContent(el, <KolBadge _color=\"#033\" _label={label}></KolBadge>);\n\t\t\t\t},\n\t\t\t\twidth: 100,\n\t\t\t},\n\t\t],\n\t],\n\tvertical: [\n\t\t[\n\t\t\t{\n\t\t\t\tlabel: 'Early',\n\t\t\t\twidth: 100,\n\t\t\t},\n\t\t\t{\n\t\t\t\tlabel: 'Noon',\n\t\t\t\twidth: 100,\n\t\t\t},\n\t\t\t{\n\t\t\t\tlabel: 'Evening',\n\t\t\t\twidth: 100,\n\t\t\t},\n\t\t\t{\n\t\t\t\tlabel: 'Night',\n\t\t\t\twidth: 100,\n\t\t\t},\n\t\t],\n\t],\n};\n\nconst renderCellContent = (element: HTMLElement, content: React.ReactNode) => {\n\tconst renderElement = document.createElement('div');\n\trenderElement.setAttribute('role', 'presentation');\n\telement.innerHTML = '';\n\telement.appendChild(renderElement);\n\tgetRoot(renderElement).render(content);\n};\n\nexport const HandoutBasic: FC = () => {\n\tconst { dummyClickEventHandler } = useAlert();\n\n\tconst dummyEventHandler = {\n\t\tonClick: dummyClickEventHandler,\n\t};\n\n\treturn (\n\t\t<div className=\"grid gap-4\">\n\t\t\t<div className=\"grid gap-4 md:grid-cols-[auto_1fr_1fr] items-center\">\n\t\t\t\t<KolKolibri className=\"block w-75px\" _labeled={false}></KolKolibri>\n\t\t\t\t<KolHeading _label=\"\" _level={1}>\n\t\t\t\t\t<span slot=\"expert\">\n\t\t\t\t\t\tKolibri-Handout <small>for {getThemeName(getTheme())}</small>\n\t\t\t\t\t</span>\n\t\t\t\t</KolHeading>\n\t\t\t\t<KolDetails _label=\"Abstract\" _open>\n\t\t\t\t\tThe handout shows a selection of KoliBri components in the style of <strong>{getThemeName(getTheme())}</strong>. Since KoliBri offers self-contained,\n\t\t\t\t\taccessible web components that can be customized to your own corporate design using theming, you don't have to develop these components yourself.\n\t\t\t\t\tFor more information read our documentation and follow us (\n\t\t\t\t\t<KolLink _label=\"https://github.com/public-ui/kolibri\" _href=\"https://github.com/public-ui/kolibri\" _target=\"_blank\" />\n\t\t\t\t\t).\n\t\t\t\t</KolDetails>\n\t\t\t</div>\n\t\t\t<div className=\"grid gap-4 sm:grid-cols-6 md:grid-cols-6 xl:grid-cols-12\">\n\t\t\t\t<KolCard className=\"col-span-6 sm:col-span-6 md:col-span-3 xl:col-span-2\" _label=\"Heading\" _level={2}>\n\t\t\t\t\t<div slot=\"\" className=\"grid gap-2 p-2\">\n\t\t\t\t\t\t<KolHeading _label=\"Heading Level 1\" _level={1}></KolHeading>\n\t\t\t\t\t\t<KolHeading _label=\"Heading Level 2\" _level={2}></KolHeading>\n\t\t\t\t\t\t<KolHeading _label=\"Heading Level 3\" _level={3}></KolHeading>\n\t\t\t\t\t\t<KolHeading _label=\"Heading Level 4\" _level={4}></KolHeading>\n\t\t\t\t\t\t<KolHeading _label=\"Heading Level 5\" _level={5}></KolHeading>\n\t\t\t\t\t\t<KolHeading _label=\"Heading Level 6\" _level={6}></KolHeading>\n\t\t\t\t\t\t<KolHeading _label=\"Heading Level 6\" _secondaryHeadline=\"Lessons\" _level={6}></KolHeading>\n\t\t\t\t\t</div>\n\t\t\t\t</KolCard>\n\t\t\t\t{/* <KolCard className=\"col-span-3\" _label=\"Accordion\" _level={2}>\n\t\t\t\t<div slot=\"\" className=\"grid gap-2 p-2\">\n\t\t\t\t\t<KolAccordion _label=\"Überschrift Level 1\" _level={1} _open>\n\t\t\t\t\t\t<div slot=\"\">Inhalt Accordion Tab 1</div>\n\t\t\t\t\t</KolAccordion>\n\t\t\t\t\t<KolAccordion _label=\"Überschrift Level 2\" _level={2}>\n\t\t\t\t\t\t<div slot=\"\">Inhalt Accordion Tab 2</div>\n\t\t\t\t\t</KolAccordion>\n\t\t\t\t\t<KolAccordion _label=\"Überschrift Level 3\" _level={3}>\n\t\t\t\t\t\t<div slot=\"\">Inhalt Accordion Tab 3</div>\n\t\t\t\t\t</KolAccordion>\n\t\t\t\t\t<KolAccordion _label=\"Überschrift Level 4\" _level={4}>\n\t\t\t\t\t\t<div slot=\"\">Inhalt Accordion Tab 4</div>\n\t\t\t\t\t</KolAccordion>\n\t\t\t\t\t<KolAccordion _label=\"Überschrift Level 5\" _level={5}>\n\t\t\t\t\t\t<div slot=\"\">Inhalt Accordion Tab 5</div>\n\t\t\t\t\t</KolAccordion>\n\t\t\t\t\t<KolAccordion _label=\"Überschrift Level 6\" _level={6}>\n\t\t\t\t\t\t<div slot=\"\">Inhalt Accordion Tab 6</div>\n\t\t\t\t\t</KolAccordion>\n\t\t\t\t</div>\n\t\t\t</KolCard> */}\n\t\t\t\t<KolCard className=\"col-span-6 sm:col-span-6 md:col-span-3 xl:col-span-2\" _label=\"Abbreviation and Progress\" _level={2}>\n\t\t\t\t\t<div slot=\"\" className=\"grid gap-2 p-2\">\n\t\t\t\t\t\t<p>\n\t\t\t\t\t\t\tI am <KolAbbr>e.g.</KolAbbr> an abbreviation.\n\t\t\t\t\t\t</p>\n\t\t\t\t\t\t<KolProgress _variant=\"bar\" _max={100} _value={33} _label=\"Progress\" />\n\t\t\t\t\t\t<KolProgress _variant=\"cycle\" _max={100} _value={66} _label=\"Progress\" />\n\t\t\t\t\t</div>\n\t\t\t\t</KolCard>\n\t\t\t\t<KolCard className=\"col-span-6 sm:col-span-6 md:col-span-6 xl:col-span-3\" _label=\"Button, LinkButton and Tab\" _level={2}>\n\t\t\t\t\t<div slot=\"\" className=\"grid gap-2 p-2\">\n\t\t\t\t\t\t<KolTabs _label=\"\" _selected={0} _tabs={[{ _label: 'Button' }, { _label: 'LinkButton' }, { _label: 'Disabled Tab', _disabled: true }]}>\n\t\t\t\t\t\t\t<div className=\"grid gap-2 py-2\">\n\t\t\t\t\t\t\t\t<div className=\"grid gap-2 grid-cols-[4fr_4fr_1fr] justify-items-center\">\n\t\t\t\t\t\t\t\t\t<KolButton _icons={{ left: 'kolicon-chevron-left' }} _label=\"primary\" _variant=\"primary\" _on={dummyEventHandler}></KolButton>\n\t\t\t\t\t\t\t\t\t<KolButton _disabled _icons={{ left: 'kolicon-chevron-left' }} _label=\"primary\" _variant=\"primary\" _on={dummyEventHandler}></KolButton>\n\t\t\t\t\t\t\t\t\t<KolButton _hideLabel _icons=\"kolicon-chevron-left\" _label=\"primary\" _variant=\"primary\" _on={dummyEventHandler}></KolButton>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div className=\"grid gap-2 grid-cols-[4fr_4fr_1fr] justify-items-center\">\n\t\t\t\t\t\t\t\t\t<KolButton _icons={{ right: 'kolicon-chevron-right' }} _label=\"secondary\" _variant=\"secondary\" _on={dummyEventHandler}></KolButton>\n\t\t\t\t\t\t\t\t\t<KolButton _disabled _icons={{ right: 'kolicon-chevron-right' }} _label=\"secondary\" _variant=\"secondary\" _on={dummyEventHandler}></KolButton>\n\t\t\t\t\t\t\t\t\t<KolButton _hideLabel _icons=\"kolicon-chevron-right\" _label=\"secondary\" _variant=\"secondary\" _on={dummyEventHandler}></KolButton>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div className=\"grid gap-2 grid-cols-[4fr_4fr_1fr] justify-items-center\">\n\t\t\t\t\t\t\t\t\t<KolButton _icons={{ top: 'kolicon-chevron-up' }} _label=\"danger\" _variant=\"danger\" _on={dummyEventHandler}></KolButton>\n\t\t\t\t\t\t\t\t\t<KolButton _disabled _icons={{ top: 'kolicon-chevron-up' }} _label=\"danger\" _variant=\"danger\" _on={dummyEventHandler}></KolButton>\n\t\t\t\t\t\t\t\t\t<KolButton _hideLabel _icons=\"kolicon-chevron-up\" _label=\"danger\" _variant=\"danger\" _on={dummyEventHandler}></KolButton>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div className=\"grid gap-2 grid-cols-[4fr_4fr_1fr] justify-items-center\">\n\t\t\t\t\t\t\t\t\t<KolButton _icons={{ bottom: 'kolicon-chevron-down' }} _label=\"normal\" _variant=\"normal\" _on={dummyEventHandler}></KolButton>\n\t\t\t\t\t\t\t\t\t<KolButton _disabled _icons={{ bottom: 'kolicon-chevron-down' }} _label=\"normal\" _variant=\"normal\" _on={dummyEventHandler}></KolButton>\n\t\t\t\t\t\t\t\t\t<KolButton _hideLabel _icons=\"kolicon-chevron-down\" _label=\"normal\" _variant=\"normal\" _on={dummyEventHandler}></KolButton>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div className=\"grid gap-2 grid-cols-[4fr_4fr_1fr] justify-items-center\">\n\t\t\t\t\t\t\t\t\t<KolButton _label=\"ghost\" _variant=\"ghost\"></KolButton>\n\t\t\t\t\t\t\t\t\t<KolButton _disabled _label=\"ghost\" _variant=\"ghost\"></KolButton>\n\t\t\t\t\t\t\t\t\t<KolButton _icons=\"kolicon-house\" _hideLabel _label=\"ghost\" _variant=\"ghost\" _on={dummyEventHandler}></KolButton>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<div className=\"grid gap-2 py-2\">\n\t\t\t\t\t\t\t\t<div className=\"grid gap-2 grid-cols-[4fr_4fr_1fr] justify-items-center\">\n\t\t\t\t\t\t\t\t\t<KolLinkButton _href=\"#/back-page\" _icons={{ left: 'kolicon-chevron-left' }} _label=\"primary\" _variant=\"primary\"></KolLinkButton>\n\t\t\t\t\t\t\t\t\t<KolLinkButton _href=\"#/back-page\" _icons={{ left: 'kolicon-chevron-left' }} _label=\"primary\" _variant=\"primary\"></KolLinkButton>\n\t\t\t\t\t\t\t\t\t<KolLinkButton _href=\"#/back-page\" _hideLabel _icons=\"kolicon-chevron-left\" _label=\"primary\" _variant=\"primary\"></KolLinkButton>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div className=\"grid gap-2 grid-cols-[4fr_4fr_1fr] justify-items-center\">\n\t\t\t\t\t\t\t\t\t<KolLinkButton _href=\"#/back-page\" _icons={{ right: 'kolicon-chevron-right' }} _label=\"secondary\" _variant=\"secondary\"></KolLinkButton>\n\t\t\t\t\t\t\t\t\t<KolLinkButton _href=\"#/back-page\" _icons={{ right: 'kolicon-chevron-right' }} _label=\"secondary\" _variant=\"secondary\"></KolLinkButton>\n\t\t\t\t\t\t\t\t\t<KolLinkButton _href=\"#/back-page\" _hideLabel _icons=\"kolicon-chevron-right\" _label=\"secondary\" _variant=\"secondary\"></KolLinkButton>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div className=\"grid gap-2 grid-cols-[4fr_4fr_1fr] justify-items-center\">\n\t\t\t\t\t\t\t\t\t<KolLinkButton _href=\"#/back-page\" _icons={{ top: 'kolicon-chevron-up' }} _label=\"danger\" _variant=\"danger\"></KolLinkButton>\n\t\t\t\t\t\t\t\t\t<KolLinkButton _href=\"#/back-page\" _icons={{ top: 'kolicon-chevron-up' }} _label=\"danger\" _variant=\"danger\"></KolLinkButton>\n\t\t\t\t\t\t\t\t\t<KolLinkButton _href=\"#/back-page\" _hideLabel _icons=\"kolicon-chevron-up\" _label=\"danger\" _variant=\"danger\"></KolLinkButton>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div className=\"grid gap-2 grid-cols-[4fr_4fr_1fr] justify-items-center\">\n\t\t\t\t\t\t\t\t\t<KolLinkButton _href=\"#/back-page\" _icons={{ bottom: 'kolicon-chevron-down' }} _label=\"normal\" _variant=\"normal\"></KolLinkButton>\n\t\t\t\t\t\t\t\t\t<KolLinkButton _href=\"#/back-page\" _icons={{ bottom: 'kolicon-chevron-down' }} _label=\"normal\" _variant=\"normal\"></KolLinkButton>\n\t\t\t\t\t\t\t\t\t<KolLinkButton _href=\"#/back-page\" _hideLabel _icons=\"kolicon-chevron-down\" _label=\"normal\" _variant=\"normal\"></KolLinkButton>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div className=\"grid gap-2 grid-cols-[4fr_4fr_1fr] justify-items-center\">\n\t\t\t\t\t\t\t\t\t<KolLinkButton _href=\"#/back-page\" _label=\"ghost\" _variant=\"ghost\"></KolLinkButton>\n\t\t\t\t\t\t\t\t\t<KolLinkButton _href=\"#/back-page\" _label=\"ghost\" _variant=\"ghost\"></KolLinkButton>\n\t\t\t\t\t\t\t\t\t<KolLinkButton _href=\"#/back-page\" _icons=\"kolicon-house\" _hideLabel _label=\"ghost\" _variant=\"ghost\"></KolLinkButton>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</KolTabs>\n\t\t\t\t\t</div>\n\t\t\t\t</KolCard>\n\t\t\t\t<KolCard className=\"col-span-6 sm:col-span-6 md:col-span-2 xl:col-span-2\" _label=\"Accordion, Link and ButtonLink\" _level={2}>\n\t\t\t\t\t<div slot=\"\" className=\"grid gap-2 p-2\">\n\t\t\t\t\t\t<KolAccordion _label=\"Links\" _level={3} _open>\n\t\t\t\t\t\t\t<div className=\"grid gap-2\" slot=\"\">\n\t\t\t\t\t\t\t\t<KolLink _href=\"#/back-page\" _label=\"Link text\"></KolLink>\n\t\t\t\t\t\t\t\t<KolLink _href=\"#/back-page\" _icons=\"kolicon-house\" _label=\"Link text with icon\"></KolLink>\n\t\t\t\t\t\t\t\t<KolLink _href=\"#/back-page\" _icons=\"kolicon-house\" _hideLabel _label=\"Link text with icon only\"></KolLink>\n\t\t\t\t\t\t\t\t<KolLink _href=\"/\" _label=\"Visited link\"></KolLink>\n\t\t\t\t\t\t\t\t<p>\n\t\t\t\t\t\t\t\t\tI am a <KolLink _href=\"#/back-page\" _label=\"externer Link\" _target=\"w3c\"></KolLink> in the running text.\n\t\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</KolAccordion>\n\t\t\t\t\t\t<KolAccordion _label=\"ButtonLinks\" _level={3}>\n\t\t\t\t\t\t\t<div className=\"grid gap-2\" slot=\"\">\n\t\t\t\t\t\t\t\t<KolButtonLink _label=\"Link text\"></KolButtonLink>\n\t\t\t\t\t\t\t\t<KolButtonLink _icons=\"kolicon-house\" _label=\"Link text with icon\"></KolButtonLink>\n\t\t\t\t\t\t\t\t<KolButtonLink _icons=\"kolicon-house\" _hideLabel _label=\"Link text with icon only\"></KolButtonLink>\n\t\t\t\t\t\t\t\t<p>\n\t\t\t\t\t\t\t\t\tI am a <KolButtonLink _label=\"Link\"></KolButtonLink> in the running text.\n\t\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t\t\t<KolButtonLink\n\t\t\t\t\t\t\t\t\t_icons={{\n\t\t\t\t\t\t\t\t\t\tleft: 'kolicon-chevron-left',\n\t\t\t\t\t\t\t\t\t\tright: 'kolicon-chevron-right',\n\t\t\t\t\t\t\t\t\t\ttop: 'kolicon-chevron-up',\n\t\t\t\t\t\t\t\t\t\tbottom: 'kolicon-chevron-down',\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t_label=\"Icons\"\n\t\t\t\t\t\t\t\t></KolButtonLink>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</KolAccordion>\n\t\t\t\t\t</div>\n\t\t\t\t</KolCard>\n\t\t\t\t<KolCard className=\"col-span-6 sm:col-span-6 md:col-span-4 xl:col-span-3\" _label=\"Alert\" _level={2}>\n\t\t\t\t\t<div slot=\"\" className=\"grid gap-2 p-2\">\n\t\t\t\t\t\t<KolAlert _label=\"Default message\" _type=\"default\">\n\t\t\t\t\t\t\tThis is the text of the alert.\n\t\t\t\t\t\t</KolAlert>\n\t\t\t\t\t\t<KolAlert _type=\"success\">Success message text</KolAlert>\n\t\t\t\t\t\t<KolAlert _type=\"error\" _hasCloser>\n\t\t\t\t\t\t\tThis is a error message text.\n\t\t\t\t\t\t</KolAlert>\n\t\t\t\t\t\t<KolAlert _label=\"Info card\" _type=\"info\" _variant=\"card\">\n\t\t\t\t\t\t\tThis is the text of the alert.\n\t\t\t\t\t\t</KolAlert>\n\t\t\t\t\t\t<KolAlert _label=\"Warning card\" _type=\"warning\" _hasCloser _variant=\"card\">\n\t\t\t\t\t\t\tThis is the text of the alert.\n\t\t\t\t\t\t</KolAlert>\n\t\t\t\t\t</div>\n\t\t\t\t</KolCard>\n\t\t\t\t<KolCard className=\"col-span-6 sm:col-span-6 md:col-span-2 xl:col-span-2\" _label=\"Nav and Breadcrumb\" _level={2}>\n\t\t\t\t\t<div slot=\"\" className=\"grid gap-2 p-2\">\n\t\t\t\t\t\t<div>\n\t\t\t\t\t\t\t<KolNav\n\t\t\t\t\t\t\t\t_label=\"Main navigation\"\n\t\t\t\t\t\t\t\t_links={[\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t_label: 'Homepage',\n\t\t\t\t\t\t\t\t\t\t_icons: 'kolicon-house',\n\t\t\t\t\t\t\t\t\t\t_href: '#/back-page',\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t_label: '2 Navigation point',\n\t\t\t\t\t\t\t\t\t\t_icons: 'kolicon-house',\n\t\t\t\t\t\t\t\t\t\t_href: '#/back-page',\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t_active: true,\n\t\t\t\t\t\t\t\t\t\t_label: '3 Navigation point',\n\t\t\t\t\t\t\t\t\t\t_href: '#/back-page',\n\t\t\t\t\t\t\t\t\t\t_icons: 'kolicon-house',\n\t\t\t\t\t\t\t\t\t\t_children: [\n\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t_label: '3.1 Navigation point',\n\t\t\t\t\t\t\t\t\t\t\t\t_icons: 'kolicon-house',\n\t\t\t\t\t\t\t\t\t\t\t\t_href: '#/back-page',\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t_label: '3.2 External navigation point',\n\t\t\t\t\t\t\t\t\t\t\t\t_icons: 'kolicon-house',\n\t\t\t\t\t\t\t\t\t\t\t\t_href: '#/back-page',\n\t\t\t\t\t\t\t\t\t\t\t\t_target: '_blank',\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t_label: '3.3 Navigation point',\n\t\t\t\t\t\t\t\t\t\t\t\t_href: '#/back-page',\n\t\t\t\t\t\t\t\t\t\t\t\t_icons: 'kolicon-house',\n\t\t\t\t\t\t\t\t\t\t\t\t_children: [\n\t\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t_active: true,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t_label: '3.3.1 Navigation point (active)',\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t_icons: 'kolicon-house',\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t_href: '#/back-page',\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t{ _label: '3.3.2 Navigation point', _icons: 'kolicon-house', _href: '#/back-page' },\n\t\t\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t{ _label: '3 Navigation point', _icons: 'kolicon-house', _href: '#/back-page' },\n\t\t\t\t\t\t\t\t]}\n\t\t\t\t\t\t\t\t_hasCompactButton\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t{/* <KolSkipNav></KolSkipNav> */}\n\t\t\t\t\t\t<div>\n\t\t\t\t\t\t\t<KolBreadcrumb\n\t\t\t\t\t\t\t\t_label=\"Breadcrumb aus Text-Links\"\n\t\t\t\t\t\t\t\t_links={[\n\t\t\t\t\t\t\t\t\t{ _label: 'Homepage', _href: '#/back-page' },\n\t\t\t\t\t\t\t\t\t{ _label: 'Bottom of the homepage', _href: '#/back-page' },\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t_label: 'Underside of the underside',\n\t\t\t\t\t\t\t\t\t\t_href: '#/back-page',\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t]}\n\t\t\t\t\t\t\t></KolBreadcrumb>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t</KolCard>\n\t\t\t\t<KolCard className=\"col-span-6 sm:col-span-6 md:col-span-4 xl:col-span-5\" _label=\"Input\" _level={2}>\n\t\t\t\t\t<KolForm slot=\"\">\n\t\t\t\t\t\t<div className=\"grid gap-4 sm:grid-cols-2 md:grid-cols-3 p-2\">\n\t\t\t\t\t\t\t<KolInputColor _label={`Color`} />\n\t\t\t\t\t\t\t<KolInputFile _label={`Upload file`} />\n\t\t\t\t\t\t\t<KolInputNumber _label={`Number input`} />\n\t\t\t\t\t\t\t<KolInputDate _type=\"date\" _label={`Date`} />\n\t\t\t\t\t\t\t<KolInputEmail\n\t\t\t\t\t\t\t\t_icons=\"{'left': 'kolicon-house'}\"\n\t\t\t\t\t\t\t\t_msg={{ _type: 'error', _description: 'Test of an error message' }}\n\t\t\t\t\t\t\t\t_touched\n\t\t\t\t\t\t\t\t_label={`E-mail address`}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t<KolInputText _hint=\"I am a hint.\" _label={`First name`} />\n\t\t\t\t\t\t\t<KolInputPassword _label={`password`} />\n\t\t\t\t\t\t\t<KolSelect _options=\"[{'label':'Mr.','value':0},{'label':'Mrs.','value':1}]\" _label={`Stimmung`} />\n\t\t\t\t\t\t\t<KolInputRange _min={0} _max={50} _value={25} _label={`Slider`} />\n\t\t\t\t\t\t\t<KolInputRadio className=\"herr-frau\" _options=\"[{'label':'Mr.','value':0},{'label':'Mrs.','value':1}]\" _value=\"1\" _label={`Salutation`} />\n\t\t\t\t\t\t\t<div className=\"grid gap-4\">\n\t\t\t\t\t\t\t\t<KolInputRadio _orientation=\"horizontal\" _options=\"[{'label':'Mr.','value':0},{'label':'Mrs.','value':1}]\" _value=\"0\" _label={`Salutation`} />\n\t\t\t\t\t\t\t\t<KolInputCheckbox _label=\"\">\n\t\t\t\t\t\t\t\t\t<span slot=\"expert\">\n\t\t\t\t\t\t\t\t\t\tI accept the <KolAbbr>AGB</KolAbbr>.\n\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t</KolInputCheckbox>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<KolTextarea _rows={4} _label={`Textarea`} />\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</KolForm>\n\t\t\t\t</KolCard>\n\t\t\t\t<KolCard className=\"col-span-6 sm:col-span-6 md:col-span-4 xl:col-span-5\" _label=\"Table with Pagination\" _level={2}>\n\t\t\t\t\t<div slot=\"\" className=\"gap-2 p-2 flex flex-col\">\n\t\t\t\t\t\t<KolTableStateful _label=\"Table\" _headers={TABLE_HEADERS} _data={TABLE_DATA} _pagination></KolTableStateful>\n\t\t\t\t\t</div>\n\t\t\t\t</KolCard>\n\t\t\t</div>\n\t\t\t<KolVersion _label=\"5.0.2-test.2\"></KolVersion>\n\t\t\t{/* <KolImage _src=\"abgrenzung.jpg\" _alt=\"KoliBri Darstellung\"></KolImage> */}\n\t\t\t{/* <KolIndentedText></KolIndentedText> */}\n\t\t\t{/* <KolQuote></KolQuote> */}\n\t\t</div>\n\t);\n};\n",
|
|
889
897
|
"kind": "sample"
|
|
890
898
|
},
|
|
891
899
|
{
|
|
@@ -1245,7 +1253,7 @@
|
|
|
1245
1253
|
"group": "input-text",
|
|
1246
1254
|
"name": "expert-slot",
|
|
1247
1255
|
"path": "packages/samples/react/src/components/input-text/expert-slot.tsx",
|
|
1248
|
-
"code": "import { KolBadge, KolIcon, KolInputText, KolPopoverButton } from '@public-ui/react-v19';\nimport * as React from 'react';\nimport { SampleBlock } from '../SampleBlock';\nimport { SampleDescription } from '../SampleDescription';\n\nexport const InputTextExpertSlot = () => {\n\treturn (\n\t\t<div className=\"grid gap-4\">\n\t\t\t<SampleDescription>\n\t\t\t\t<p>This sample shows KolInputText with expert slot. The expert slot allows for complex custom content beyond simple text inputs.</p>\n\t\t\t</SampleDescription>\n\n\t\t\t<SampleBlock id=\"text\">\n\t\t\t\t<KolInputText _label=\"\" _type=\"text\">\n\t\t\t\t\t<span slot=\"expert\">I am more than just a input field</span>\n\t\t\t\t</KolInputText>\n\t\t\t</SampleBlock>\n\t\t\t<SampleBlock id=\"badge\">\n\t\t\t\t<KolInputText _label=\"\" _type=\"text\" _value=\"Complex example\">\n\t\t\t\t\t<div slot=\"expert\" className=\"flex items-center gap-2\">\n\t\t\t\t\t\t<KolBadge _label=\"Premium\" _color=\"#1a73e8\" />\n\t\t\t\t\t\t<KolIcon _icons=\"kolicon-check\" _label=\"\" />\n\t\t\t\t\t\t<span>Verified account with premium features</span>\n\t\t\t\t\t</div>\n\t\t\t\t</KolInputText>\n\t\t\t</SampleBlock>\n\t\t\t<SampleBlock id=\"note\">\n\t\t\t\t<KolInputText _label=\"\" _type=\"text\" _placeholder=\"Enter your email\">\n\t\t\t\t\t<div slot=\"expert\" style={{ padding: '0.5rem', backgroundColor: '#f0f0f0', borderRadius: '4px' }}>\n\t\t\t\t\t\t<strong>Note:</strong> This email will be used for account recovery and notifications.\n\t\t\t\t\t</div>\n\t\t\t\t</KolInputText>\n\t\t\t</SampleBlock>\n\t\t\t<SampleBlock id=\"required\">\n\t\t\t\t<KolInputText _label=\"\" _type=\"text\" _required>\n\t\t\t\t\t<div slot=\"expert\" className=\"inline-block\">\n\t\t\t\t\t\t<span className=\"expert-slot-required-label\">Username</span>\n\t\t\t\t\t\t<KolPopoverButton _label=\"Help\" _icons=\"kolicon-alert-info\" _variant=\"ghost\" _hideLabel _inline>\n\t\t\t\t\t\t\t<div className=\"w-sm p-2 border border-solid border-gray\">You have to take care of the asterics on your own!</div>\n\t\t\t\t\t\t</KolPopoverButton>\n\t\t\t\t\t</div>\n\t\t\t\t</KolInputText>\n\t\t\t</SampleBlock>\n\t\t\t<SampleBlock id=\"readonly\">\n\t\t\t\t<KolInputText _label=\"\" _type=\"text\" _readOnly _value=\"(read only) is also not appended\">\n\t\t\t\t\t<div slot=\"expert\" className=\"inline-block\">\n\t\t\t\t\t\t<span className=\"expert-slot-required-label\">Username</span>\n\t\t\t\t\t\t<KolPopoverButton _label=\"Help\" _icons=\"kolicon-alert-info\" _variant=\"ghost\" _hideLabel _inline>\n\t\t\t\t\t\t\t<div className=\"w-sm p-2 border border-solid border-gray\">Readonly is also not appended</div>\n\t\t\t\t\t\t</KolPopoverButton>\n\t\t\t\t\t</div>\n\t\t\t\t</KolInputText>\n\t\t\t</SampleBlock>\n\t\t</div>\n\t);\n};\n",
|
|
1256
|
+
"code": "import { KolBadge, KolIcon, KolInputText, KolPopoverButton } from '@public-ui/react-v19';\nimport * as React from 'react';\nimport { SampleBlock } from '../SampleBlock';\nimport { SampleDescription } from '../SampleDescription';\n\nexport const InputTextExpertSlot = () => {\n\treturn (\n\t\t<div className=\"grid gap-4\">\n\t\t\t<SampleDescription>\n\t\t\t\t<p>This sample shows KolInputText with expert slot. The expert slot allows for complex custom content beyond simple text inputs.</p>\n\t\t\t\t<p>\n\t\t\t\t\tFor further information on the expert slot see its <a href=\"https://public-ui.github.io/docs/concepts/expert-slot\">documentation</a>\n\t\t\t\t</p>\n\t\t\t</SampleDescription>\n\n\t\t\t<SampleBlock id=\"text\">\n\t\t\t\t<KolInputText _label=\"\" _type=\"text\">\n\t\t\t\t\t<span slot=\"expert\">I am more than just a input field</span>\n\t\t\t\t</KolInputText>\n\t\t\t</SampleBlock>\n\t\t\t<SampleBlock id=\"badge\">\n\t\t\t\t<KolInputText _label=\"\" _type=\"text\" _value=\"Complex example\">\n\t\t\t\t\t<div slot=\"expert\" className=\"flex items-center gap-2\">\n\t\t\t\t\t\t<KolBadge _label=\"Premium\" _color=\"#1a73e8\" />\n\t\t\t\t\t\t<KolIcon _icons=\"kolicon-check\" _label=\"\" />\n\t\t\t\t\t\t<span>Verified account with premium features</span>\n\t\t\t\t\t</div>\n\t\t\t\t</KolInputText>\n\t\t\t</SampleBlock>\n\t\t\t<SampleBlock id=\"note\">\n\t\t\t\t<KolInputText _label=\"\" _type=\"text\" _placeholder=\"Enter your email\">\n\t\t\t\t\t<div slot=\"expert\" style={{ padding: '0.5rem', backgroundColor: '#f0f0f0', borderRadius: '4px' }}>\n\t\t\t\t\t\t<strong>Note:</strong> This email will be used for account recovery and notifications.\n\t\t\t\t\t</div>\n\t\t\t\t</KolInputText>\n\t\t\t</SampleBlock>\n\t\t\t<SampleBlock id=\"required\">\n\t\t\t\t<KolInputText _label=\"\" _type=\"text\" _required>\n\t\t\t\t\t<div slot=\"expert\" className=\"inline-block\">\n\t\t\t\t\t\t<span className=\"expert-slot-required-label\">Username</span>\n\t\t\t\t\t\t<KolPopoverButton _label=\"Help\" _icons=\"kolicon-alert-info\" _variant=\"ghost\" _hideLabel _inline>\n\t\t\t\t\t\t\t<div className=\"w-sm p-2 border border-solid border-gray\">You have to take care of the asterics on your own!</div>\n\t\t\t\t\t\t</KolPopoverButton>\n\t\t\t\t\t</div>\n\t\t\t\t</KolInputText>\n\t\t\t</SampleBlock>\n\t\t\t<SampleBlock id=\"readonly\">\n\t\t\t\t<KolInputText _label=\"\" _type=\"text\" _readOnly _value=\"(read only) is also not appended\">\n\t\t\t\t\t<div slot=\"expert\" className=\"inline-block\">\n\t\t\t\t\t\t<span className=\"expert-slot-required-label\">Username</span>\n\t\t\t\t\t\t<KolPopoverButton _label=\"Help\" _icons=\"kolicon-alert-info\" _variant=\"ghost\" _hideLabel _inline>\n\t\t\t\t\t\t\t<div className=\"w-sm p-2 border border-solid border-gray\">Readonly is also not appended</div>\n\t\t\t\t\t\t</KolPopoverButton>\n\t\t\t\t\t</div>\n\t\t\t\t</KolInputText>\n\t\t\t</SampleBlock>\n\t\t</div>\n\t);\n};\n",
|
|
1249
1257
|
"kind": "sample"
|
|
1250
1258
|
},
|
|
1251
1259
|
{
|
|
@@ -1365,7 +1373,7 @@
|
|
|
1365
1373
|
"group": "link-button",
|
|
1366
1374
|
"name": "basic",
|
|
1367
1375
|
"path": "packages/samples/react/src/components/link-button/basic.tsx",
|
|
1368
|
-
"code": "import React, { useMemo } from 'react';\n\nimport { KolLinkButton } from '@public-ui/react-v19';\n\nimport type { FC } from 'react';\nimport { useSearchParams } from 'react-router';\nimport {
|
|
1376
|
+
"code": "import React, { useMemo } from 'react';\n\nimport { KolLinkButton } from '@public-ui/react-v19';\n\nimport type { FC } from 'react';\nimport { useSearchParams } from 'react-router';\nimport { useAlert } from '../../hooks/useAlert';\nimport { fetchVariantData } from '../../shares/fetchVariantData';\nimport { getTheme } from '../../shares/store';\nimport { SampleBlock } from '../SampleBlock';\nimport { SampleDescription } from '../SampleDescription';\n\nexport const LinkButtonBasic: FC = () => {\n\tconst [searchParams] = useSearchParams();\n\tconst theme = searchParams.get('theme') ?? getTheme();\n\tconst data = useMemo(() => (theme ? fetchVariantData(theme, 'buttonVariants') : []), [theme]);\n\n\tconst { dummyClickEventHandler } = useAlert();\n\n\tconst dummyEventHandler = {\n\t\tonClick: dummyClickEventHandler,\n\t};\n\treturn (\n\t\t<>\n\t\t\t<SampleDescription>\n\t\t\t\t<p>KolLinkButton renders a link that looks like a button. The sample shows the different theme exclusive styling variants.</p>\n\t\t\t</SampleDescription>\n\n\t\t\t<div className=\"grid gap-8\">\n\t\t\t\t<SampleBlock id=\"variants\">\n\t\t\t\t\t<div className=\"flex flex-wrap gap-4 items-center\">\n\t\t\t\t\t\t{!Array.isArray(data) || data.length === 0 ? (\n\t\t\t\t\t\t\t<p>This theme has no variants for this component.</p>\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\tdata.map((element) => {\n\t\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t\t<KolLinkButton _href=\"#/back-page\" _icons=\"kolicon-house\" _label={`${element}`} _variant={element} key={element} _on={dummyEventHandler} />\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t)}\n\t\t\t\t\t</div>\n\t\t\t\t\t<div className=\"flex flex-wrap gap-4 items-center\">\n\t\t\t\t\t\t{!Array.isArray(data) || data.length === 0 ? (\n\t\t\t\t\t\t\t<p>This theme has no variants for this component.</p>\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\tdata.map((element) => {\n\t\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t\t<KolLinkButton\n\t\t\t\t\t\t\t\t\t\t_href=\"#/back-page\"\n\t\t\t\t\t\t\t\t\t\t_hideLabel\n\t\t\t\t\t\t\t\t\t\t_icons=\"kolicon-settings\"\n\t\t\t\t\t\t\t\t\t\t_label={`${element}`}\n\t\t\t\t\t\t\t\t\t\t_variant={element}\n\t\t\t\t\t\t\t\t\t\tkey={element}\n\t\t\t\t\t\t\t\t\t\t_on={dummyEventHandler}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t)}\n\t\t\t\t\t</div>\n\t\t\t\t</SampleBlock>\n\t\t\t</div>\n\t\t</>\n\t);\n};\n",
|
|
1369
1377
|
"kind": "sample"
|
|
1370
1378
|
},
|
|
1371
1379
|
{
|
|
@@ -1432,6 +1440,14 @@
|
|
|
1432
1440
|
"code": "import type { FC } from 'react';\nimport React from 'react';\n\nimport { KolHeading, KolLink } from '@public-ui/react-v19';\nimport { SampleDescription } from '../SampleDescription';\n\nexport const LinkHeadline: FC = () => (\n\t<>\n\t\t<SampleDescription>\n\t\t\t<p>This sample shows a linked headline with anchor.</p>\n\t\t</SampleDescription>\n\n\t\t<div className=\"grid gap-4\">\n\t\t\t<KolLink _href=\"/#/link/linked-headline#headline1\" _label=\"\">\n\t\t\t\t<KolHeading _label=\"I'm H2-heading number one\" _level={2} slot=\"expert\" id=\"headline1\" />\n\t\t\t</KolLink>\n\t\t\t<p>\n\t\t\t\tLorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam\n\t\t\t\tvoluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.\n\t\t\t\tLorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam\n\t\t\t\tvoluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.\n\t\t\t</p>\n\t\t\t<p>\n\t\t\t\tLorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam\n\t\t\t\tvoluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.\n\t\t\t\tLorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam\n\t\t\t\tvoluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.\n\t\t\t</p>\n\t\t\t<p>\n\t\t\t\tLorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam\n\t\t\t\tvoluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.\n\t\t\t\tLorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam\n\t\t\t\tvoluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.\n\t\t\t</p>\n\t\t\t<KolLink _href=\"/#/link/linked-headline#headline2\" _label=\"\">\n\t\t\t\t<KolHeading _label=\"I'm H2-heading number two\" _level={2} slot=\"expert\" id=\"headline2\" />\n\t\t\t</KolLink>\n\t\t\t<p>\n\t\t\t\tLorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam\n\t\t\t\tvoluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.\n\t\t\t\tLorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam\n\t\t\t\tvoluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.\n\t\t\t</p>\n\t\t\t<p>\n\t\t\t\tLorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam\n\t\t\t\tvoluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.\n\t\t\t\tLorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam\n\t\t\t\tvoluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.\n\t\t\t</p>\n\t\t\t<p>\n\t\t\t\tLorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam\n\t\t\t\tvoluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.\n\t\t\t\tLorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam\n\t\t\t\tvoluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.\n\t\t\t</p>\n\t\t\t<KolLink _href=\"/#/link/linked-headline#headline3\" _label=\"\">\n\t\t\t\t<KolHeading _label=\"I'm H2-heading number three\" _level={2} slot=\"expert\" id=\"headline3\" />\n\t\t\t</KolLink>\n\t\t\t<p>\n\t\t\t\tLorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam\n\t\t\t\tvoluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.\n\t\t\t\tLorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam\n\t\t\t\tvoluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.\n\t\t\t</p>\n\t\t\t<p>\n\t\t\t\tLorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam\n\t\t\t\tvoluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.\n\t\t\t\tLorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam\n\t\t\t\tvoluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.\n\t\t\t</p>\n\t\t\t<p>\n\t\t\t\tLorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam\n\t\t\t\tvoluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.\n\t\t\t\tLorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam\n\t\t\t\tvoluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.\n\t\t\t</p>\n\t\t</div>\n\t</>\n);\n",
|
|
1433
1441
|
"kind": "sample"
|
|
1434
1442
|
},
|
|
1443
|
+
{
|
|
1444
|
+
"id": "sample/link/on-click",
|
|
1445
|
+
"group": "link",
|
|
1446
|
+
"name": "on-click",
|
|
1447
|
+
"path": "packages/samples/react/src/components/link/on-click.tsx",
|
|
1448
|
+
"code": "import type { FC } from 'react';\nimport React, { useState } from 'react';\n\nimport { KolLink } from '@public-ui/react-v19';\nimport { SampleBlock } from '../SampleBlock';\nimport { SampleDescription } from '../SampleDescription';\n\nexport const LinkOnClick: FC = () => {\n\tconst [clickCount, setClickCount] = useState(0);\n\n\t// Test 1: onClick ohne preventDefault - sollte navigieren UND onClick ausführen\n\tconst onClickWithoutPrevent = {\n\t\tonClick: (event: Event, href: string) => {\n\t\t\tconsole.log('Test 1: onClick ohne preventDefault', { event, href });\n\t\t\tsetClickCount((c) => c + 1);\n\t\t\t// Kein preventDefault - Navigation sollte stattfinden\n\t\t},\n\t};\n\n\t// Test 2: onClick mit preventDefault - sollte NUR onClick ausführen, NICHT navigieren\n\tconst onClickWithPrevent = {\n\t\tonClick: (event: Event, href: string) => {\n\t\t\tconsole.log('Test 2: onClick mit preventDefault', { event, href });\n\t\t\tsetClickCount((c) => c + 1);\n\t\t\tevent.preventDefault();\n\t\t\t// Navigation sollte blockiert sein\n\t\t},\n\t};\n\n\t// Test 3: onClick mit return false - sollte NUR onClick ausführen, NICHT navigieren\n\tconst onClickWithReturnFalse = {\n\t\tonClick: (event: Event, href: string) => {\n\t\t\tconsole.log('Test 3: onClick mit return false', { event, href });\n\t\t\tsetClickCount((c) => c + 1);\n\t\t\treturn false;\n\t\t\t// Navigation sollte blockiert sein\n\t\t},\n\t};\n\n\t// Test 4: onClick mit useNavigate (React Router Pattern)\n\t// Dies ist der Use-Case aus Issue #10726\n\tconst onClickWithNavigate = {\n\t\tonClick: (event: Event, href: string) => {\n\t\t\tconsole.log('Test 4: onClick mit simulate navigate', { event, href });\n\t\t\tsetClickCount((c) => c + 1);\n\t\t\tevent.preventDefault();\n\t\t\t// Simuliere useNavigate.navigate(\"/home\") - sollte NICHT zu href navigieren\n\t\t\tconsole.log('Simulated navigate to:', href);\n\t\t},\n\t};\n\n\treturn (\n\t\t<>\n\t\t\t<SampleDescription>\n\t\t\t\t<p>\n\t\t\t\t\tThis sample demonstrates the issue described in{' '}\n\t\t\t\t\t<a href=\"https://github.com/public-ui/kolibri/issues/10726\" target=\"_blank\" rel=\"noopener noreferrer\">\n\t\t\t\t\t\t#10726\n\t\t\t\t\t</a>\n\t\t\t\t\t.\n\t\t\t\t\t<br />\n\t\t\t\t\tTest the behavior of KolLink with onClick handlers and compare it to native <a> tags.\n\t\t\t\t</p>\n\t\t\t\t<p>\n\t\t\t\t\t<strong>Expected behavior (like native <a> tag):</strong>\n\t\t\t\t\t<ul>\n\t\t\t\t\t\t<li>onClick without preventDefault: Execute onClick AND navigate to href</li>\n\t\t\t\t\t\t<li>onClick with preventDefault: Execute onClick, BLOCK navigation</li>\n\t\t\t\t\t\t<li>onClick returning false: Execute onClick, BLOCK navigation</li>\n\t\t\t\t\t</ul>\n\t\t\t\t</p>\n\t\t\t\t<p>\n\t\t\t\t\t<strong>Current behavior (Issue #10726):</strong>\n\t\t\t\t\t<ul>\n\t\t\t\t\t\t<li>❌ onClick with preventDefault: Still navigates to href (should only execute onClick)</li>\n\t\t\t\t\t\t<li>❌ onClick returning false: Still navigates to href (should only execute onClick)</li>\n\t\t\t\t\t</ul>\n\t\t\t\t</p>\n\t\t\t</SampleDescription>\n\n\t\t\t<SampleBlock id=\"on-click\">\n\t\t\t\t<div className=\"grid gap-4\">\n\t\t\t\t\t{/* Info Panel */}\n\t\t\t\t\t<div className=\"bg-gray-100 p-4 rounded\">\n\t\t\t\t\t\t<h2 className=\"h3 mb-2\">Test Results</h2>\n\t\t\t\t\t\t<p>\n\t\t\t\t\t\t\t<strong>onClick executions:</strong> {clickCount}\n\t\t\t\t\t\t</p>\n\t\t\t\t\t\t<p className=\"text-sm text-gray-600\">(Open browser console to see detailed logs)</p>\n\t\t\t\t\t\t<p className=\"text-sm text-gray-600\">\n\t\t\t\t\t\t\tNote: This demo uses href="#test" to avoid actual page reloads. Check the URL hash and console output.\n\t\t\t\t\t\t</p>\n\t\t\t\t\t</div>\n\n\t\t\t\t\t{/* Test 1: onClick ohne preventDefault */}\n\t\t\t\t\t<div className=\"bg-white p-4 rounded border\">\n\t\t\t\t\t\t<h3 className=\"h4 mb-2\">Test 1: onClick ohne preventDefault</h3>\n\t\t\t\t\t\t<p className=\"text-sm text-gray-600 mb-2\">Expected: Click increments counter AND adds #test-1 to URL</p>\n\t\t\t\t\t\t<KolLink _href=\"#test-1\" _label=\"Click me (no preventDefault)\" _on={onClickWithoutPrevent} _inline={false} />\n\t\t\t\t\t</div>\n\n\t\t\t\t\t{/* Test 2: onClick mit preventDefault */}\n\t\t\t\t\t<div className=\"bg-white p-4 rounded border\">\n\t\t\t\t\t\t<h3 className=\"h4 mb-2\">Test 2: onClick mit preventDefault()</h3>\n\t\t\t\t\t\t<p className=\"text-sm text-gray-600 mb-2\">Expected: Click increments counter but does NOT add #test-2 to URL</p>\n\t\t\t\t\t\t<KolLink _href=\"#test-2\" _label=\"Click me (with preventDefault)\" _on={onClickWithPrevent} _inline={false} />\n\t\t\t\t\t</div>\n\n\t\t\t\t\t{/* Test 3: onClick mit return false */}\n\t\t\t\t\t<div className=\"bg-white p-4 rounded border\">\n\t\t\t\t\t\t<h3 className=\"h4 mb-2\">Test 3: onClick returning false</h3>\n\t\t\t\t\t\t<p className=\"text-sm text-gray-600 mb-2\">Expected: Click increments counter but does NOT add #test-3 to URL</p>\n\t\t\t\t\t\t<KolLink _href=\"#test-3\" _label=\"Click me (return false)\" _on={onClickWithReturnFalse} _inline={false} />\n\t\t\t\t\t</div>\n\n\t\t\t\t\t{/* Test 4: useNavigate Pattern (Issue #10726) */}\n\t\t\t\t\t<div className=\"bg-white p-4 rounded border\">\n\t\t\t\t\t\t<h3 className=\"h4 mb-2\">Test 4: useNavigate Pattern (Issue #10726)</h3>\n\t\t\t\t\t\t<p className=\"text-sm text-gray-600 mb-2\">Expected: Click logs navigate action but does NOT add #test-4 to URL</p>\n\t\t\t\t\t\t<KolLink _href=\"#test-4\" _label=\"Click me (simulate useNavigate)\" _on={onClickWithNavigate} _inline={false} />\n\t\t\t\t\t</div>\n\n\t\t\t\t\t{/* Vergleich: Natives <a>-Tag */}\n\t\t\t\t\t<div className=\"bg-white p-4 rounded border\">\n\t\t\t\t\t\t<h3 className=\"h4 mb-2\">Reference: Native <a> Tag</h3>\n\t\t\t\t\t\t<p className=\"text-sm text-gray-600 mb-2\">Test native <a> tag behavior for comparison</p>\n\t\t\t\t\t\t<div className=\"grid gap-2\">\n\t\t\t\t\t\t\t<a\n\t\t\t\t\t\t\t\thref=\"#native-test-1\"\n\t\t\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\t\t\tconsole.log('Native a: onClick ohne preventDefault');\n\t\t\t\t\t\t\t\t\tsetClickCount((c) => c + 1);\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\tclassName=\"btn btn-primary\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\tNative: No preventDefault\n\t\t\t\t\t\t\t</a>\n\t\t\t\t\t\t\t<a\n\t\t\t\t\t\t\t\thref=\"#native-test-2\"\n\t\t\t\t\t\t\t\tonClick={(event: React.MouseEvent) => {\n\t\t\t\t\t\t\t\t\tconsole.log('Native a: onClick mit preventDefault');\n\t\t\t\t\t\t\t\t\tsetClickCount((c) => c + 1);\n\t\t\t\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\tclassName=\"btn btn-primary\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\tNative: With preventDefault\n\t\t\t\t\t\t\t</a>\n\t\t\t\t\t\t\t<a\n\t\t\t\t\t\t\t\thref=\"#native-test-3\"\n\t\t\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\t\t\tconsole.log('Native a: onClick mit return false');\n\t\t\t\t\t\t\t\t\tsetClickCount((c) => c + 1);\n\t\t\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\tclassName=\"btn btn-primary\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\tNative: Return false\n\t\t\t\t\t\t\t</a>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</SampleBlock>\n\t\t</>\n\t);\n};\n",
|
|
1449
|
+
"kind": "sample"
|
|
1450
|
+
},
|
|
1435
1451
|
{
|
|
1436
1452
|
"id": "sample/link/react-router",
|
|
1437
1453
|
"group": "link",
|
|
@@ -1541,7 +1557,7 @@
|
|
|
1541
1557
|
"group": "popover-button",
|
|
1542
1558
|
"name": "basic",
|
|
1543
1559
|
"path": "packages/samples/react/src/components/popover-button/basic.tsx",
|
|
1544
|
-
"code": "import type { ToolbarItemsPropType } from '@public-ui/components';\nimport { KolHeading, KolPopoverButton, KolToolbar } from '@public-ui/react-v19';\nimport type { FC } from 'react';\nimport React, { useEffect } from 'react';\nimport {
|
|
1560
|
+
"code": "import type { ToolbarItemsPropType } from '@public-ui/components';\nimport { KolHeading, KolPopoverButton, KolToolbar } from '@public-ui/react-v19';\nimport type { FC } from 'react';\nimport React, { useEffect } from 'react';\nimport { useAlert } from '../../hooks/useAlert';\nimport { SampleDescription } from '../SampleDescription';\n\nexport const PopoverButtonBasic: FC = () => {\n\tconst { dummyClickEventHandler } = useAlert();\n\tconst buttonRef = React.useRef<HTMLKolPopoverButtonElement | null>(null);\n\n\tconst dummyEventHandler = {\n\t\tonClick: dummyClickEventHandler,\n\t};\n\n\tconst TOOLBAR_ITEMS: ToolbarItemsPropType = [\n\t\t{\n\t\t\ttype: 'button',\n\t\t\t_label: 'Show',\n\t\t\t_icons: 'kolicon-eye',\n\t\t\t_on: dummyEventHandler,\n\t\t},\n\t\t{\n\t\t\ttype: 'button',\n\t\t\t_label: 'Delete',\n\t\t\t_icons: 'kolicon-minus',\n\t\t\t_on: dummyEventHandler,\n\t\t},\n\t\t{\n\t\t\ttype: 'button',\n\t\t\t_label: 'Add',\n\t\t\t_icons: 'kolicon-plus',\n\t\t\t_on: dummyEventHandler,\n\t\t},\n\t];\n\n\tuseEffect(() => {\n\t\t// Ensure the popover is closed on initial render\n\t\tif (buttonRef.current) {\n\t\t\tbuttonRef.current.showPopover();\n\t\t\tbuttonRef.current.focus();\n\t\t}\n\t}, []);\n\n\treturn (\n\t\t<>\n\t\t\t<SampleDescription>\n\t\t\t\t<p>\n\t\t\t\t\tThe PopoverButton component combines a button with a popover that appears when clicked. The popover can be positioned in different directions (top,\n\t\t\t\t\tright, bottom, left) using the <code>_popoverAlign</code> prop.\n\t\t\t\t</p>\n\t\t\t</SampleDescription>\n\t\t\t<div className=\"flex flex-col gap-4 items-center\">\n\t\t\t\t<KolPopoverButton _label={'Actions'} _variant=\"primary\" _icons={{ right: 'kolicon-chevron-down' }} ref={buttonRef}>\n\t\t\t\t\t<KolToolbar _label=\"Action toolbar\" _items={TOOLBAR_ITEMS} _orientation=\"vertical\" />\n\t\t\t\t</KolPopoverButton>\n\t\t\t\t<KolPopoverButton _label=\"Help\" _icons=\"kolicon-alert-info\" _popoverAlign=\"right\" _tooltipAlign=\"bottom\" _hideLabel>\n\t\t\t\t\t<div className=\"w-sm p-2 border border-solid border-gray bg-white\">\n\t\t\t\t\t\t<KolHeading _label=\"Help Information\" _level={0}></KolHeading>\n\t\t\t\t\t\t<p>\n\t\t\t\t\t\t\t<u>Lorem ipsum dolor sit amet</u>, consectetur adipisicing elit. Aspernatur aut dolore dolores itaque praesentium reprehenderit sed voluptatum!\n\t\t\t\t\t\t\tExercitationem ipsa magni maiores modi, placeat quas quos reprehenderit rerum sit veniam vitae.\n\t\t\t\t\t\t</p>\n\t\t\t\t\t</div>\n\t\t\t\t</KolPopoverButton>\n\t\t\t</div>\n\t\t</>\n\t);\n};\n",
|
|
1545
1561
|
"kind": "sample"
|
|
1546
1562
|
},
|
|
1547
1563
|
{
|
|
@@ -1653,7 +1669,7 @@
|
|
|
1653
1669
|
"group": "split-button",
|
|
1654
1670
|
"name": "basic",
|
|
1655
1671
|
"path": "packages/samples/react/src/components/split-button/basic.tsx",
|
|
1656
|
-
"code": "import React from 'react';\n\nimport type { ToolbarItemsPropType } from '@public-ui/components';\nimport { KolSplitButton, KolToolbar } from '@public-ui/react-v19';\nimport {
|
|
1672
|
+
"code": "import React from 'react';\n\nimport type { ToolbarItemsPropType } from '@public-ui/components';\nimport { KolSplitButton, KolToolbar } from '@public-ui/react-v19';\nimport { SampleBlock } from '../SampleBlock';\nimport { SampleDescription } from '../SampleDescription';\n\nimport type { FC } from 'react';\nimport { useAlert } from '../../hooks/useAlert';\n\nexport const SplitButtonBasic: FC = () => {\n\tconst { buttonWithTextClickEventHandler } = useAlert();\n\tconst dummyEventHandler = {\n\t\tonClick: buttonWithTextClickEventHandler,\n\t};\n\tconst TOOLBAR_ITEMS: ToolbarItemsPropType = [\n\t\t{\n\t\t\ttype: 'button',\n\t\t\t_label: 'Save',\n\t\t\t_icons: 'kolicon-check',\n\t\t\t_on: dummyEventHandler,\n\t\t},\n\t\t{\n\t\t\ttype: 'button',\n\t\t\t_label: 'Move Up',\n\t\t\t_icons: 'kolicon-chevron-up',\n\t\t\t_on: dummyEventHandler,\n\t\t},\n\t\t{\n\t\t\ttype: 'button',\n\t\t\t_label: 'Delete',\n\t\t\t_icons: 'kolicon-minus',\n\t\t\t_on: dummyEventHandler,\n\t\t},\n\t];\n\n\treturn (\n\t\t<>\n\t\t\t<SampleDescription>\n\t\t\t\t<p>\n\t\t\t\t\tThe <code>SplitButton</code> component combines a primary action button with a context menu. Clicking the main button triggers the\n\t\t\t\t\t<strong> Edit</strong> action. The context menu opens a vertical list of additional actions:\n\t\t\t\t\t<strong> Save</strong>, <strong>Move</strong>, and <strong>Delete</strong>.\n\t\t\t\t</p>\n\t\t\t</SampleDescription>\n\n\t\t\t<SampleBlock id=\"basic\" className=\"flex flex-col gap-4\">\n\t\t\t\t<KolSplitButton _label=\"Edit\" _on={dummyEventHandler}>\n\t\t\t\t\t<KolToolbar _label=\"Action toolbar\" _items={TOOLBAR_ITEMS} _orientation=\"vertical\" />\n\t\t\t\t</KolSplitButton>\n\t\t\t</SampleBlock>\n\t\t</>\n\t);\n};\n",
|
|
1657
1673
|
"kind": "sample"
|
|
1658
1674
|
},
|
|
1659
1675
|
{
|
|
@@ -1677,7 +1693,7 @@
|
|
|
1677
1693
|
"group": "table",
|
|
1678
1694
|
"name": "action-columns",
|
|
1679
1695
|
"path": "packages/samples/react/src/components/table/action-columns.tsx",
|
|
1680
|
-
"code": "import type { KoliBriTableHeaderCellWithLogic } from '@public-ui/components';\nimport { KolTableStateful } from '@public-ui/react-v19';\nimport type { FC } from 'react';\nimport React from 'react';\nimport { SampleBlock } from '../SampleBlock';\nimport { SampleDescription } from '../SampleDescription';\n\ntype ProjectTask = {\n\tid: string;\n\tproject: string;\n\towner: string;\n};\n\nconst HEADERS: { horizontal: KoliBriTableHeaderCellWithLogic[][] } = {\n\thorizontal: [\n\t\t[\n\t\t\t{ key: 'id', label: 'ID', width: 80 },\n\t\t\t{ key: 'project', label: 'Project' },\n\t\t\t{ key: 'owner', label: 'Owner', width: 140 },\n\t\t\t{\n\t\t\t\ttype: 'action',\n\t\t\t\tkey: 'actions',\n\t\t\t\tlabel: 'Actions',\n\t\t\t\twidth: 250,\n\t\t\t\tactions: (row) => {\n\t\t\t\t\tconst simpleRow = row as ProjectTask;\n\t\t\t\t\treturn [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttype: 'button',\n\t\t\t\t\t\t\t_label: 'Details',\n\t\t\t\t\t\t\t_icons: 'kolicon-eye',\n\t\t\t\t\t\t\t_hideLabel: true,\n\t\t\t\t\t\t\t_on: {\n\t\t\t\t\t\t\t\tonClick: () => alert(`Details: ${simpleRow.id} - ${simpleRow.project}`),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttype: 'button',\n\t\t\t\t\t\t\t_label: 'Start',\n\t\t\t\t\t\t\t_icons: 'kolicon-chevron-right',\n\t\t\t\t\t\t\t_variant: 'secondary',\n\t\t\t\t\t\t\t_on: {\n\t\t\t\t\t\t\t\tonClick: () => alert(`Start task ${simpleRow.id}`),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttype: 'link',\n\t\t\t\t\t\t\t_label: 'View',\n\t\t\t\t\t\t\t_href: `#/back-page?taskId=${simpleRow.id}`,\n\t\t\t\t\t\t\t_target: '_blank',\n\t\t\t\t\t\t\t_icons: 'kolicon-external-link',\n\t\t\t\t\t\t\t_hideLabel: false,\n\t\t\t\t\t\t},\n\t\t\t\t\t];\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\ttype: 'action',\n\t\t\t\tkey: 'externalActions',\n\t\t\t\tlabel: 'External Actions',\n\t\t\t\twidth: 280,\n\t\t\t\tactions: (row) => {\n\t\t\t\t\tconst simpleRow = row as ProjectTask;\n\t\t\t\t\treturn [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttype: 'link',\n\t\t\t\t\t\t\t_label: 'View on Dashboard',\n\t\t\t\t\t\t\t_href: `#/back-page?taskId=${simpleRow.id}`,\n\t\t\t\t\t\t\t_target: '_blank',\n\t\t\t\t\t\t\t_icons: 'kolicon-external-link',\n\t\t\t\t\t\t\t_hideLabel: false,\n\t\t\t\t\t\t},\n\t\t\t\t\t];\n\t\t\t\t},\n\t\t\t},\n\t\t],\n\t],\n};\n\nconst DATA: ProjectTask[] = [\n\t{\n\t\tid: 'T-01',\n\t\tproject: 'Onboarding checklist',\n\t\towner: 'Alex Rivera',\n\t},\n\t{\n\t\tid: 'T-02',\n\t\tproject: 'Accessibility audit',\n\t\towner: 'Jamie Chen',\n\t},\n];\n\nexport const TableActionColumns: FC = () => (\n\t<>\n\t\t<SampleDescription>\n\t\t\t<p>\n\t\t\t\tSimple example using the refactored action column: Actions are defined once in the column header definition using a factory function. Two rows with\n\t\t\t\tinline action buttons demonstrate clean separation between data and UI behavior.\n\t\t\t</p>\n\t\t</SampleDescription>\n\n\t\t<SampleBlock id=\"action-columns\" className=\"w-full\">\n\t\t\t<KolTableStateful _label=\"Tasks with action buttons\" _headers={HEADERS} _data={DATA} className=\"block\" />\n\t\t</SampleBlock>\n\t</>\n);\n",
|
|
1696
|
+
"code": "import type { KoliBriTableHeaderCellWithLogic } from '@public-ui/components';\nimport { KolTableStateful } from '@public-ui/react-v19';\nimport type { FC } from 'react';\nimport React from 'react';\nimport { SampleBlock } from '../SampleBlock';\nimport { SampleDescription } from '../SampleDescription';\n\ntype ProjectTask = {\n\tid: string;\n\tproject: string;\n\towner: string;\n};\n\nconst HEADERS: { horizontal: KoliBriTableHeaderCellWithLogic[][] } = {\n\thorizontal: [\n\t\t[\n\t\t\t{ key: 'id', label: 'ID', width: 80 },\n\t\t\t{ key: 'project', label: 'Project' },\n\t\t\t{ key: 'owner', label: 'Owner', width: 140 },\n\t\t\t{\n\t\t\t\ttype: 'action',\n\t\t\t\tkey: 'actions',\n\t\t\t\tlabel: 'Actions',\n\t\t\t\ttextAlign: 'left',\n\t\t\t\twidth: 250,\n\t\t\t\tactions: (row) => {\n\t\t\t\t\tconst simpleRow = row as ProjectTask;\n\t\t\t\t\treturn [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttype: 'button',\n\t\t\t\t\t\t\t_label: 'Details',\n\t\t\t\t\t\t\t_icons: 'kolicon-eye',\n\t\t\t\t\t\t\t_hideLabel: true,\n\t\t\t\t\t\t\t_on: {\n\t\t\t\t\t\t\t\tonClick: () => alert(`Details: ${simpleRow.id} - ${simpleRow.project}`),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttype: 'button',\n\t\t\t\t\t\t\t_label: 'Start',\n\t\t\t\t\t\t\t_icons: 'kolicon-chevron-right',\n\t\t\t\t\t\t\t_variant: 'secondary',\n\t\t\t\t\t\t\t_on: {\n\t\t\t\t\t\t\t\tonClick: () => alert(`Start task ${simpleRow.id}`),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttype: 'link',\n\t\t\t\t\t\t\t_label: 'View',\n\t\t\t\t\t\t\t_href: `#/back-page?taskId=${simpleRow.id}`,\n\t\t\t\t\t\t\t_target: '_blank',\n\t\t\t\t\t\t\t_icons: 'kolicon-external-link',\n\t\t\t\t\t\t\t_hideLabel: false,\n\t\t\t\t\t\t},\n\t\t\t\t\t];\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\ttype: 'action',\n\t\t\t\tkey: 'externalActions',\n\t\t\t\tlabel: 'External Actions',\n\t\t\t\ttextAlign: 'right',\n\t\t\t\twidth: 280,\n\t\t\t\tactions: (row) => {\n\t\t\t\t\tconst simpleRow = row as ProjectTask;\n\t\t\t\t\treturn [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttype: 'link',\n\t\t\t\t\t\t\t_label: 'View on Dashboard',\n\t\t\t\t\t\t\t_href: `#/back-page?taskId=${simpleRow.id}`,\n\t\t\t\t\t\t\t_target: '_blank',\n\t\t\t\t\t\t\t_icons: 'kolicon-external-link',\n\t\t\t\t\t\t\t_hideLabel: false,\n\t\t\t\t\t\t},\n\t\t\t\t\t];\n\t\t\t\t},\n\t\t\t},\n\t\t],\n\t],\n};\n\nconst DATA: ProjectTask[] = [\n\t{\n\t\tid: 'T-01',\n\t\tproject: 'Onboarding checklist',\n\t\towner: 'Alex Rivera',\n\t},\n\t{\n\t\tid: 'T-02',\n\t\tproject: 'Accessibility audit',\n\t\towner: 'Jamie Chen',\n\t},\n];\n\nexport const TableActionColumns: FC = () => (\n\t<>\n\t\t<SampleDescription>\n\t\t\t<p>\n\t\t\t\tSimple example using the refactored action column: Actions are defined once in the column header definition using a factory function. Two rows with\n\t\t\t\tinline action buttons demonstrate clean separation between data and UI behavior.\n\t\t\t</p>\n\t\t</SampleDescription>\n\n\t\t<SampleBlock id=\"action-columns\" className=\"w-full\">\n\t\t\t<KolTableStateful _label=\"Tasks with action buttons\" _headers={HEADERS} _data={DATA} className=\"block\" />\n\t\t</SampleBlock>\n\t</>\n);\n",
|
|
1681
1697
|
"kind": "sample"
|
|
1682
1698
|
},
|
|
1683
1699
|
{
|
|
@@ -1757,7 +1773,7 @@
|
|
|
1757
1773
|
"group": "table",
|
|
1758
1774
|
"name": "interactive-child-elements",
|
|
1759
1775
|
"path": "packages/samples/react/src/components/table/interactive-child-elements.tsx",
|
|
1760
|
-
"code": "import type { KoliBriTableCell, KoliBriTableHeaderCell, VariantClassNamePropType } from '@public-ui/components';\nimport { createReactRenderElement, KolButton, KolButtonLink, KolLink, KolLinkButton, KolTableStateless } from '@public-ui/react-v19';\nimport type { ComponentProps, FC } from 'react';\nimport React from 'react';\nimport {
|
|
1776
|
+
"code": "import type { KoliBriTableCell, KoliBriTableHeaderCell, VariantClassNamePropType } from '@public-ui/components';\nimport { createReactRenderElement, KolButton, KolButtonLink, KolLink, KolLinkButton, KolTableStateless } from '@public-ui/react-v19';\nimport type { ComponentProps, FC } from 'react';\nimport React from 'react';\nimport { useAlert } from '../../hooks/useAlert';\nimport { getRoot } from '../../shares/react-roots';\nimport { SampleDescription } from '../SampleDescription';\n\ntype KolButtonProps = ComponentProps<typeof KolButton>;\n\nfunction KolButtonWrapper(props: KolButtonProps) {\n\tconst { dummyClickEventHandler } = useAlert();\n\tconst dummyEventHandler = {\n\t\tonClick: dummyClickEventHandler,\n\t};\n\treturn <KolButton {...props} _on={dummyEventHandler} />;\n}\n\nconst getButtonHeaderCell = (variant: VariantClassNamePropType): KoliBriTableHeaderCell => {\n\tconst variantLabel = `${variant}`;\n\tconst capitalizedVariant = variantLabel.charAt(0).toUpperCase() + variantLabel.slice(1);\n\treturn {\n\t\tlabel: capitalizedVariant,\n\t\tkey: variantLabel,\n\t\ttextAlign: 'left',\n\t\twidth: 160,\n\t\trender: (element: HTMLElement, cell: KoliBriTableCell) => {\n\t\t\tconst { label } = cell as { label: string };\n\t\t\tconst commonProps = {\n\t\t\t\t_label: capitalizedVariant,\n\t\t\t\t_variant: variant,\n\t\t\t\t_icons: { right: 'kolicon-kolibri' },\n\t\t\t};\n\t\t\tgetRoot(createReactRenderElement(element)).render(\n\t\t\t\tlabel === 'button' ? <KolButtonWrapper {...commonProps} /> : <KolLinkButton _href=\"#/back-page\" {...commonProps} />,\n\t\t\t);\n\t\t},\n\t};\n};\n\nexport const InteractiveChildElements: FC = () => (\n\t<>\n\t\t<SampleDescription>\n\t\t\t<p>\n\t\t\t\tThis sample shows a KolTableStateless with different interactive child elements. It can be used to assure themes show these child elements correctly.\n\t\t\t</p>\n\t\t</SampleDescription>\n\n\t\t<section className=\"w-full flex flex-col\">\n\t\t\t<KolTableStateless\n\t\t\t\t_label=\"Button styles\"\n\t\t\t\t_headerCells={{\n\t\t\t\t\thorizontal: [\n\t\t\t\t\t\t[\n\t\t\t\t\t\t\tgetButtonHeaderCell('primary'),\n\t\t\t\t\t\t\tgetButtonHeaderCell('secondary'),\n\t\t\t\t\t\t\tgetButtonHeaderCell('normal'),\n\t\t\t\t\t\t\tgetButtonHeaderCell('danger'),\n\t\t\t\t\t\t\tgetButtonHeaderCell('ghost'),\n\t\t\t\t\t\t],\n\t\t\t\t\t],\n\t\t\t\t\tvertical: [\n\t\t\t\t\t\t[\n\t\t\t\t\t\t\t{ label: 'Button', width: 120 },\n\t\t\t\t\t\t\t{ label: 'Link-Button', width: 120 },\n\t\t\t\t\t\t],\n\t\t\t\t\t],\n\t\t\t\t}}\n\t\t\t\t_data={[\n\t\t\t\t\t{\n\t\t\t\t\t\tprimary: 'button',\n\t\t\t\t\t\tsecondary: 'button',\n\t\t\t\t\t\tnormal: 'button',\n\t\t\t\t\t\tdanger: 'button',\n\t\t\t\t\t\tghost: 'button',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tprimary: 'link-button',\n\t\t\t\t\t\tsecondary: 'link-button',\n\t\t\t\t\t\tnormal: 'link-button',\n\t\t\t\t\t\tdanger: 'link-button',\n\t\t\t\t\t\tghost: 'link-button',\n\t\t\t\t\t},\n\t\t\t\t]}\n\t\t\t\tclassName=\"block\"\n\t\t\t/>\n\n\t\t\t<KolTableStateless\n\t\t\t\t_label=\"Link styles\"\n\t\t\t\t_headerCells={{\n\t\t\t\t\thorizontal: [\n\t\t\t\t\t\t[\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tkey: 'regular',\n\t\t\t\t\t\t\t\tlabel: 'Regular',\n\t\t\t\t\t\t\t\ttextAlign: 'left',\n\t\t\t\t\t\t\t\twidth: 180,\n\t\t\t\t\t\t\t\trender: (element: HTMLElement, cell: KoliBriTableCell) => {\n\t\t\t\t\t\t\t\t\tconst { label } = cell as { label: string };\n\t\t\t\t\t\t\t\t\tconst commonProps = {\n\t\t\t\t\t\t\t\t\t\t_label: label,\n\t\t\t\t\t\t\t\t\t\t_icons: { right: 'kolicon-kolibri' },\n\t\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t\t\tgetRoot(createReactRenderElement(element)).render(\n\t\t\t\t\t\t\t\t\t\tlabel === 'button-link' ? <KolButtonLink {...commonProps} /> : <KolLink _href=\"#/back-page\" {...commonProps} />,\n\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t],\n\t\t\t\t\t],\n\t\t\t\t\tvertical: [\n\t\t\t\t\t\t[\n\t\t\t\t\t\t\t{ label: 'Link', width: 140 },\n\t\t\t\t\t\t\t{ label: 'Button-Link', width: 140 },\n\t\t\t\t\t\t],\n\t\t\t\t\t],\n\t\t\t\t}}\n\t\t\t\t_data={[\n\t\t\t\t\t{\n\t\t\t\t\t\tregular: 'link',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tregular: 'button-link',\n\t\t\t\t\t},\n\t\t\t\t]}\n\t\t\t\tclassName=\"block mt\"\n\t\t\t/>\n\t\t</section>\n\t</>\n);\n",
|
|
1761
1777
|
"kind": "sample"
|
|
1762
1778
|
},
|
|
1763
1779
|
{
|
|
@@ -1797,7 +1813,7 @@
|
|
|
1797
1813
|
"group": "table",
|
|
1798
1814
|
"name": "render-cell",
|
|
1799
1815
|
"path": "packages/samples/react/src/components/table/render-cell.tsx",
|
|
1800
|
-
"code": "import type { FC } from 'react';\nimport React from 'react';\n\nimport { createReactRenderElement, KolButton, KolInputText, KolTableStateful } from '@public-ui/react-v19';\n\nimport { getRoot } from '../../shares/react-roots';\nimport { SampleDescription } from '../SampleDescription';\nimport { DATE_FORMATTER } from './formatter';\n\nimport type { IconsPropType, KoliBriTableCell, KoliBriTableHeaders } from '@public-ui/components';\nimport {
|
|
1816
|
+
"code": "import type { FC } from 'react';\nimport React from 'react';\n\nimport { createReactRenderElement, KolButton, KolInputText, KolTableStateful } from '@public-ui/react-v19';\n\nimport { getRoot } from '../../shares/react-roots';\nimport { SampleDescription } from '../SampleDescription';\nimport { DATE_FORMATTER } from './formatter';\n\nimport type { IconsPropType, KoliBriTableCell, KoliBriTableHeaders } from '@public-ui/components';\nimport { useAlert } from '../../hooks/useAlert';\n\ntype Data = {\n\torder: number;\n\tdate: Date;\n\tshipped: boolean;\n};\n\n/**\n * Generates n data entries with random dates and shipping status\n * @param n - Number of data entries to generate\n * @returns Array of Data objects\n */\nfunction generateDataEntries(n: number): Data[] {\n\tconst entries: Data[] = [];\n\tconst startDate = new Date('1970-01-01').getTime();\n\tconst endDate = new Date('2025-12-31').getTime();\n\n\tfor (let i = 0; i < n; i++) {\n\t\tconst randomTimestamp = startDate + Math.random() * (endDate - startDate);\n\t\tentries.push({\n\t\t\torder: i,\n\t\t\tshipped: Math.random() > 0.5,\n\t\t\tdate: new Date(randomTimestamp),\n\t\t});\n\t}\n\n\treturn entries;\n}\n\nconst DATA: Data[] = generateDataEntries(100);\n\nfunction KolButtonWrapper({ label, icons }: { label: string; icons: IconsPropType }) {\n\tconst { dummyClickEventHandler } = useAlert();\n\n\tconst dummyEventHandler = {\n\t\tonClick: dummyClickEventHandler,\n\t};\n\n\treturn <KolButton _label={label} _icons={icons} _on={dummyEventHandler} />;\n}\n\nconst HEADERS: KoliBriTableHeaders = {\n\thorizontal: [\n\t\t[\n\t\t\t{\n\t\t\t\tlabel: '#',\n\t\t\t\tkey: 'order',\n\t\t\t\ttextAlign: 'center',\n\t\t\t\twidth: 100,\n\n\t\t\t\t/* Example 1: Use render return value to format data */\n\t\t\t\trender: (_el, cell: KoliBriTableCell) => {\n\t\t\t\t\tconst { label } = cell as { label: string };\n\t\t\t\t\treturn `Index: ${label}`;\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tlabel: 'Status',\n\t\t\t\tkey: 'shipped',\n\t\t\t\ttextAlign: 'center',\n\t\t\t\twidth: 100,\n\n\t\t\t\t/* Example 2: Simple render function using textContent */\n\t\t\t\trender: (el, cell: KoliBriTableCell) => {\n\t\t\t\t\tconst { label } = cell as { label: string };\n\t\t\t\t\tconst element = el as HTMLElement;\n\t\t\t\t\tif (label) {\n\t\t\t\t\t\telement.textContent = `Order has been dispatched 🚚`;\n\t\t\t\t\t} else {\n\t\t\t\t\t\telement.textContent = `Order pending 📦`;\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tlabel: 'Date (string)',\n\t\t\t\tkey: 'date',\n\t\t\t\twidth: 200,\n\t\t\t\ttextAlign: 'center',\n\n\t\t\t\t/* Example 3: Render function using innerHTML. ⚠️Make sure to sanitize data to avoid XSS. */\n\t\t\t\trender: (el, cell: KoliBriTableCell) => {\n\t\t\t\t\tconst { label } = cell as { label: string };\n\t\t\t\t\t(el as HTMLElement).innerHTML = `<strong>${DATE_FORMATTER.format(label as unknown as Date)}</strong>`;\n\t\t\t\t},\n\t\t\t\tcompareFn: (data0, data1) => (data0 as Data).date.getTime() - (data1 as Data).date.getTime(),\n\t\t\t},\n\t\t\t{\n\t\t\t\tlabel: 'Action (react)',\n\t\t\t\tkey: 'action',\n\t\t\t\twidth: 200,\n\n\t\t\t\t/* Example 4: Render function using React */\n\t\t\t\trender: (el) => {\n\t\t\t\t\tgetRoot(createReactRenderElement(el)).render(\n\t\t\t\t\t\t<div\n\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\tdisplay: `grid`,\n\t\t\t\t\t\t\t\tgridAutoFlow: `column`,\n\t\t\t\t\t\t\t\talignItems: `end`,\n\t\t\t\t\t\t\t\tgap: `1rem`,\n\t\t\t\t\t\t\t\tmaxWidth: `400px`,\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<KolInputText _label=\"Input\" />\n\t\t\t\t\t\t\t<KolButtonWrapper label=\"Save\" icons={{ left: 'kolicon-check' }} />\n\t\t\t\t\t\t</div>,\n\t\t\t\t\t);\n\t\t\t\t},\n\t\t\t},\n\t\t],\n\t],\n};\n\nexport const TableRenderCell: FC = () => (\n\t<>\n\t\t<SampleDescription>\n\t\t\t<p>This sample shows KolTableStateful using React render functions for the cell contents.</p>\n\t\t</SampleDescription>\n\n\t\t<KolTableStateful _label=\"Sort by date column\" _data={DATA} _headers={HEADERS} className=\"w-full\" _hasSettingsMenu />\n\t</>\n);\n",
|
|
1801
1817
|
"kind": "sample"
|
|
1802
1818
|
},
|
|
1803
1819
|
{
|
|
@@ -1885,7 +1901,7 @@
|
|
|
1885
1901
|
"group": "table",
|
|
1886
1902
|
"name": "stateless-with-selection",
|
|
1887
1903
|
"path": "packages/samples/react/src/components/table/stateless-with-selection.tsx",
|
|
1888
|
-
"code": "import type { KoliBriTableCell, KoliBriTableSelection, KoliBriTableSelectionKeys } from '@public-ui/components';\nimport { createReactRenderElement, KolButton, KolTableStateless } from '@public-ui/react-v19';\nimport type { FC } from 'react';\nimport React, { useEffect, useRef, useState } from 'react';\nimport {
|
|
1904
|
+
"code": "import type { KoliBriTableCell, KoliBriTableSelection, KoliBriTableSelectionKeys } from '@public-ui/components';\nimport { createReactRenderElement, KolButton, KolTableStateless } from '@public-ui/react-v19';\nimport type { FC } from 'react';\nimport React, { useEffect, useRef, useState } from 'react';\nimport { useAlert } from '../../hooks/useAlert';\nimport { getRoot } from '../../shares/react-roots';\nimport { SampleBlock } from '../SampleBlock';\nimport { SampleDescription } from '../SampleDescription';\n\ntype SelectionValue = string | number;\ntype KolTableStatelessElement = {\n\taddEventListener: (type: string, listener: (event: CustomEvent<SelectionValue[]>) => void) => void;\n\tremoveEventListener: (type: string, listener: (event: CustomEvent<SelectionValue[]>) => void) => void;\n};\n\nconst DATA = [\n\t{ id: '1001', name: 'Foo Bar', internalIdentifier: `AAA1001` },\n\t{ id: '1002', name: 'Foo Baz', internalIdentifier: `AAA1002` },\n\t{ id: '1003', name: 'This row is always unchecked', internalIdentifier: `AAA1003` },\n\t{ id: '1004', name: 'This row is always checked', internalIdentifier: `AAA1004` },\n];\ntype Data = (typeof DATA)[0];\n\nfunction KolButtonWrapper({ label }: { label: string }) {\n\tconst { dummyClickEventHandler } = useAlert();\n\n\tconst dummyEventHandler = {\n\t\tonClick: dummyClickEventHandler,\n\t};\n\n\treturn <KolButton _label={label} _on={dummyEventHandler} />;\n}\n\nexport const TableStatelessWithSelection: FC = () => {\n\tconst [selectedKeys, setSelectedKeys] = useState<KoliBriTableSelectionKeys>(['AAA1002', 'AAA1004']);\n\n\tconst selection: KoliBriTableSelection = {\n\t\tlabel: (row) => `Selection for ${(row as Data).name}`,\n\t\tselectedKeys,\n\t\tkeyPropertyName: 'internalIdentifier',\n\t\tdisabledKeys: ['AAA1003', 'AAA1004'],\n\t};\n\n\tconst kolTableStatelessRef = useRef<HTMLKolTableStatelessElement>(null);\n\n\tconst handleSelectionChangeEvent = ({ detail: selection }: CustomEvent<SelectionValue[]>) => {\n\t\tconsole.log('Selection change via event', selection);\n\t};\n\tconst handleSelectionChangeCallback = (_event: Event, selection: SelectionValue[]) => {\n\t\tconsole.log('Selection change via callback', selection);\n\t\tsetSelectedKeys(selection);\n\t};\n\n\tuseEffect(() => {\n\t\tconst tableElement = kolTableStatelessRef.current as unknown as KolTableStatelessElement | null;\n\t\tconst selectionChangeEvent = 'kolSelectionChange';\n\t\ttableElement?.addEventListener(selectionChangeEvent, handleSelectionChangeEvent);\n\n\t\treturn () => {\n\t\t\ttableElement?.removeEventListener(selectionChangeEvent, handleSelectionChangeEvent);\n\t\t};\n\t}, [kolTableStatelessRef]);\n\n\tconst renderButton = (element: HTMLElement, cell: KoliBriTableCell) => {\n\t\tconst data = (cell as { data?: Data }).data;\n\t\tconst id = data?.id;\n\t\tgetRoot(createReactRenderElement(element)).render(<KolButtonWrapper label={`Click ${id}`} />);\n\t};\n\n\treturn (\n\t\t<>\n\t\t\t<SampleDescription>\n\t\t\t\t<p>This sample shows KolTableStateless with checkboxes for selection enabled.</p>\n\t\t\t</SampleDescription>\n\n\t\t\t<SampleBlock id=\"selection\" className=\"w-full\">\n\t\t\t\t<KolTableStateless\n\t\t\t\t\t_label=\"Table with selection checkboxes\"\n\t\t\t\t\t_headerCells={{\n\t\t\t\t\t\thorizontal: [\n\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t{ key: 'id', label: '#ID', textAlign: 'left' },\n\t\t\t\t\t\t\t\t{ key: 'name', label: 'Name', textAlign: 'left' },\n\t\t\t\t\t\t\t\t{ key: 'action', label: 'Action', textAlign: 'left', render: renderButton },\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t],\n\t\t\t\t\t}}\n\t\t\t\t\t_data={DATA}\n\t\t\t\t\t_selection={selection}\n\t\t\t\t\t_on={{ onSelectionChange: handleSelectionChangeCallback }}\n\t\t\t\t\tclassName=\"block\"\n\t\t\t\t\tstyle={{ maxWidth: '600px' }}\n\t\t\t\t\tref={kolTableStatelessRef}\n\t\t\t\t/>\n\t\t\t</SampleBlock>\n\t\t</>\n\t);\n};\n",
|
|
1889
1905
|
"kind": "sample"
|
|
1890
1906
|
},
|
|
1891
1907
|
{
|
|
@@ -1901,7 +1917,7 @@
|
|
|
1901
1917
|
"group": "table",
|
|
1902
1918
|
"name": "stateless-with-single-selection",
|
|
1903
1919
|
"path": "packages/samples/react/src/components/table/stateless-with-single-selection.tsx",
|
|
1904
|
-
"code": "import type { KoliBriTableCell, KoliBriTableSelection, KoliBriTableSelectionKeys } from '@public-ui/components';\nimport { createReactRenderElement, KolButton, KolTableStateless } from '@public-ui/react-v19';\nimport type { FC } from 'react';\nimport React, { useCallback, useEffect, useRef, useState } from 'react';\nimport {
|
|
1920
|
+
"code": "import type { KoliBriTableCell, KoliBriTableSelection, KoliBriTableSelectionKeys } from '@public-ui/components';\nimport { createReactRenderElement, KolButton, KolTableStateless } from '@public-ui/react-v19';\nimport type { FC } from 'react';\nimport React, { useCallback, useEffect, useRef, useState } from 'react';\nimport { useAlert } from '../../hooks/useAlert';\nimport { getRoot } from '../../shares/react-roots';\nimport { SampleBlock } from '../SampleBlock';\nimport { SampleDescription } from '../SampleDescription';\n\ntype SelectionValue = string | number;\ntype KolTableStatelessElement = {\n\taddEventListener: (type: string, listener: (event: CustomEvent<SelectionValue[]>) => void) => void;\n\tremoveEventListener: (type: string, listener: (event: CustomEvent<SelectionValue[]>) => void) => void;\n};\n\nconst DATA = [\n\t{ id: '1001', name: 'Foo Bar', internalIdentifier: `AAA1001` },\n\t{ id: '1002', name: 'Foo Baz', internalIdentifier: `AAA1002` },\n\t{ id: '1003', name: 'Foo Disabled', internalIdentifier: `AAA1003` },\n];\ntype Data = (typeof DATA)[0];\n\nfunction KolButtonWrapper({ label }: { label: string }) {\n\tconst { dummyClickEventHandler } = useAlert();\n\n\tconst dummyEventHandler = {\n\t\tonClick: dummyClickEventHandler,\n\t};\n\n\treturn <KolButton _label={label} _on={dummyEventHandler} />;\n}\n\nexport const TableStatelessWithSingleSelection: FC = () => {\n\tconst [selectedKeys, setSelectedKeys] = useState<KoliBriTableSelectionKeys>(['1002']);\n\n\tconst selection: KoliBriTableSelection = {\n\t\tlabel: (row) => `Selection for ${(row as Data).name}`,\n\t\tmultiple: false,\n\t\tselectedKeys,\n\t\tdisabledKeys: ['AAA1003'],\n\t\tkeyPropertyName: 'internalIdentifier',\n\t};\n\n\tconst kolTableStatelessRef = useRef<HTMLKolTableStatelessElement>(null);\n\n\tconst handleSelectionChangeEvent = useCallback(({ detail: selection }: CustomEvent<SelectionValue[]>) => {\n\t\tconsole.log('Selection change via event', selection);\n\t}, []);\n\tconst handleSelectionChangeCallback = useCallback((_event: Event, selection: SelectionValue[]) => {\n\t\tconsole.log('Selection change via callback', selection);\n\t\tsetSelectedKeys(selection);\n\t}, []);\n\n\tuseEffect(() => {\n\t\tconst tableElement = kolTableStatelessRef.current as unknown as KolTableStatelessElement | null;\n\t\tconst selectionChangeEvent = 'kolSelectionChange';\n\t\ttableElement?.addEventListener(selectionChangeEvent, handleSelectionChangeEvent);\n\n\t\treturn () => {\n\t\t\ttableElement?.removeEventListener(selectionChangeEvent, handleSelectionChangeEvent);\n\t\t};\n\t}, [kolTableStatelessRef, handleSelectionChangeEvent]);\n\n\tconst renderButton = useCallback((element: HTMLElement, cell: KoliBriTableCell) => {\n\t\tconst data = (cell as { data?: Data }).data;\n\t\tconst id = data?.id;\n\t\tgetRoot(createReactRenderElement(element)).render(<KolButtonWrapper label={`Click ${id}`} />);\n\t}, []);\n\n\treturn (\n\t\t<>\n\t\t\t<SampleDescription>\n\t\t\t\t<p>This sample shows KolTableStateless with checkboxes for selection enabled.</p>\n\t\t\t</SampleDescription>\n\n\t\t\t<SampleBlock id=\"single-selection\" className=\"w-full\" fitContent>\n\t\t\t\t<KolTableStateless\n\t\t\t\t\t_label=\"Table with selection checkboxes\"\n\t\t\t\t\t_headerCells={{\n\t\t\t\t\t\thorizontal: [\n\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t{ key: 'id', label: '#ID', textAlign: 'left' },\n\t\t\t\t\t\t\t\t{ key: 'name', label: 'Name', textAlign: 'left' },\n\t\t\t\t\t\t\t\t{ key: 'action', label: 'Action', textAlign: 'left', render: renderButton },\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t],\n\t\t\t\t\t}}\n\t\t\t\t\t_data={DATA}\n\t\t\t\t\t_selection={selection}\n\t\t\t\t\t_on={{ onSelectionChange: handleSelectionChangeCallback }}\n\t\t\t\t\tclassName=\"block\"\n\t\t\t\t\tstyle={{ maxWidth: '600px' }}\n\t\t\t\t\tref={kolTableStatelessRef}\n\t\t\t\t/>\n\t\t\t</SampleBlock>\n\t\t</>\n\t);\n};\n",
|
|
1905
1921
|
"kind": "sample"
|
|
1906
1922
|
},
|
|
1907
1923
|
{
|
|
@@ -2117,7 +2133,7 @@
|
|
|
2117
2133
|
"group": "scenarios",
|
|
2118
2134
|
"name": "custom-tooltip-css-properties",
|
|
2119
2135
|
"path": "packages/samples/react/src/scenarios/custom-tooltip-css-properties.tsx",
|
|
2120
|
-
"code": "import type { FC } from 'react';\nimport React from 'react';\n\nimport { KolButton } from '@public-ui/react-v19';\nimport { SampleDescription } from '../components/SampleDescription';\nimport {
|
|
2136
|
+
"code": "import type { FC } from 'react';\nimport React from 'react';\n\nimport { KolButton } from '@public-ui/react-v19';\nimport { SampleDescription } from '../components/SampleDescription';\nimport { useAlert } from '../hooks/useAlert';\n\nexport const CustomTooltipCssProperties: FC = () => {\n\tconst { dummyClickEventHandler } = useAlert();\n\n\tconst dummyEventHandler = {\n\t\tonClick: dummyClickEventHandler,\n\t};\n\n\treturn (\n\t\t<>\n\t\t\t<SampleDescription>\n\t\t\t\t<p>\n\t\t\t\t\tThis sample demonstrates how tooltip animation duration and width can be customized via\n\t\t\t\t\t<code>--kolibri-tooltip-animation-duration</code> and <code>--kol-tooltip-width</code>.\n\t\t\t\t</p>\n\t\t\t</SampleDescription>\n\n\t\t\t<div className=\"flex justify-center items-center gap-4\">\n\t\t\t\t<KolButton\n\t\t\t\t\t_label=\"Custom duration\"\n\t\t\t\t\t_hideLabel\n\t\t\t\t\tstyle={{ '--kolibri-tooltip-animation-duration': '2500ms' }}\n\t\t\t\t\t_icons=\"fa-solid fa-clock\"\n\t\t\t\t\t_on={dummyEventHandler}\n\t\t\t\t></KolButton>\n\t\t\t\t<KolButton _label=\"Custom width\" _hideLabel style={{ '--kol-tooltip-width': '400px' }} _icons=\"kolicon-chevron-up\" _on={dummyEventHandler}></KolButton>\n\t\t\t</div>\n\t\t</>\n\t);\n};\n",
|
|
2121
2137
|
"kind": "scenario"
|
|
2122
2138
|
},
|
|
2123
2139
|
{
|
|
@@ -2133,7 +2149,7 @@
|
|
|
2133
2149
|
"group": "scenarios",
|
|
2134
2150
|
"name": "disabled-interactive-scenario",
|
|
2135
2151
|
"path": "packages/samples/react/src/scenarios/disabled-interactive-elements.tsx",
|
|
2136
|
-
"code": "import {\n\tKolAccordion,\n\tKolButton,\n\tKolButtonLink,\n\tKolCard,\n\tKolDetails,\n\tKolInputCheckbox,\n\tKolInputColor,\n\tKolInputDate,\n\tKolInputEmail,\n\tKolInputFile,\n\tKolInputNumber,\n\tKolInputPassword,\n\tKolInputRadio,\n\tKolInputRange,\n\tKolInputText,\n\tKolLink,\n\tKolLinkButton,\n\tKolSelect,\n\tKolTextarea,\n} from '@public-ui/react-v19';\nimport type { FC } from 'react';\nimport React from 'react';\nimport { SampleDescription } from '../components/SampleDescription';\nimport {
|
|
2152
|
+
"code": "import {\n\tKolAccordion,\n\tKolButton,\n\tKolButtonLink,\n\tKolCard,\n\tKolDetails,\n\tKolInputCheckbox,\n\tKolInputColor,\n\tKolInputDate,\n\tKolInputEmail,\n\tKolInputFile,\n\tKolInputNumber,\n\tKolInputPassword,\n\tKolInputRadio,\n\tKolInputRange,\n\tKolInputText,\n\tKolLink,\n\tKolLinkButton,\n\tKolSelect,\n\tKolTextarea,\n} from '@public-ui/react-v19';\nimport type { FC } from 'react';\nimport React from 'react';\nimport { SampleDescription } from '../components/SampleDescription';\nimport { useAlert } from '../hooks/useAlert';\n\nconst OPTIONS = [\n\t{\n\t\tlabel: 'Option A',\n\t\tvalue: 'A',\n\t},\n\t{\n\t\tlabel: 'Option B',\n\t\tvalue: 'B',\n\t},\n];\n\nexport const DisabledInteractiveElements: FC = () => {\n\tconst { dummyClickEventHandler } = useAlert();\n\n\tconst dummyEventHandler = {\n\t\tonClick: dummyClickEventHandler,\n\t};\n\n\treturn (\n\t\t<>\n\t\t\t<SampleDescription>\n\t\t\t\t<p>This example shows how deactivated interactive elements are displayed.</p>\n\t\t\t\t<ul>\n\t\t\t\t\t<li>Deactivated interactive elements pose a particular challenge for accessibility.</li>\n\t\t\t\t\t<li>It must not be possible to focus on deactivated interactive elements, otherwise the tab paths will be unnecessarily extended.</li>\n\t\t\t\t\t<li>Deactivated interactive elements should be labelled clearly and legibly.</li>\n\t\t\t\t\t<li>\n\t\t\t\t\t\tDeactivated interactive elements have a tooltip for sighted people and aria labelling for the screen readers reading mode if they are represented by\n\t\t\t\t\t\tan interpretable graphic.\n\t\t\t\t\t</li>\n\t\t\t\t</ul>\n\t\t\t\t<p>This implementation ensures standardized use for all users.</p>\n\t\t\t</SampleDescription>\n\n\t\t\t<div className=\"w-full grid gap-4\">\n\t\t\t\t<KolCard _label=\"Button\" _level={0}>\n\t\t\t\t\t<div className=\"flex flex-wrap gap-4\">\n\t\t\t\t\t\t<KolButton _label=\"Label\" _on={dummyEventHandler} />\n\t\t\t\t\t\t<KolButton _disabled _label=\"Label\" _on={dummyEventHandler} />\n\t\t\t\t\t\t<KolButton _hideLabel _icons=\"fa-solid fa-house\" _label=\"Label\" _on={dummyEventHandler} />\n\t\t\t\t\t\t<KolButton _disabled _hideLabel _icons=\"fa-solid fa-house\" _label=\"Label\" _on={dummyEventHandler} />\n\t\t\t\t\t</div>\n\t\t\t\t</KolCard>\n\t\t\t\t<KolCard _label=\"ButtonLink\" _level={0}>\n\t\t\t\t\t<div className=\"flex flex-wrap gap-4\">\n\t\t\t\t\t\t<KolButtonLink _label=\"Label\" />\n\t\t\t\t\t\t<KolButtonLink _disabled _label=\"Label\" />\n\t\t\t\t\t\t<KolButtonLink _hideLabel _icons=\"fa-solid fa-house\" _label=\"Label\" />\n\t\t\t\t\t\t<KolButtonLink _hideLabel _icons=\"fa-solid fa-house\" _disabled _label=\"Label\" />\n\t\t\t\t\t</div>\n\t\t\t\t</KolCard>\n\t\t\t\t<KolCard _label=\"Link\" _level={0}>\n\t\t\t\t\t<div className=\"flex flex-wrap gap-4\">\n\t\t\t\t\t\t<KolLink _href=\"#\" _label=\"Label\" />\n\t\t\t\t\t\t<KolLink _disabled _href=\"#\" _label=\"Label\" />\n\t\t\t\t\t\t<KolLink _hideLabel _href=\"#\" _icons=\"fa-solid fa-house\" _label=\"Label\" />\n\t\t\t\t\t\t<KolLink _disabled _hideLabel _href=\"#\" _icons=\"fa-solid fa-house\" _label=\"Label\" />\n\t\t\t\t\t</div>\n\t\t\t\t</KolCard>\n\t\t\t\t<KolCard _label=\"LinkButton\" _level={0}>\n\t\t\t\t\t<div className=\"flex flex-wrap gap-4\">\n\t\t\t\t\t\t<KolLinkButton _href=\"#\" _label=\"Label\" />\n\t\t\t\t\t\t<KolLinkButton _disabled _href=\"#\" _label=\"Label\" />\n\t\t\t\t\t\t<KolLinkButton _hideLabel _href=\"#\" _icons=\"fa-solid fa-house\" _label=\"Label\" />\n\t\t\t\t\t\t<KolLinkButton _disabled _hideLabel _href=\"#\" _icons=\"fa-solid fa-house\" _label=\"Label\" />\n\t\t\t\t\t</div>\n\t\t\t\t</KolCard>\n\t\t\t\t<KolCard _label=\"Accordion\" _level={0}>\n\t\t\t\t\t<div className=\"grid gap-4\">\n\t\t\t\t\t\t<KolAccordion _label=\"Label\">Content</KolAccordion>\n\t\t\t\t\t\t<KolAccordion _disabled _label=\"Label\">\n\t\t\t\t\t\t\tContent\n\t\t\t\t\t\t</KolAccordion>\n\t\t\t\t\t\t<KolAccordion _label=\"Label (open)\" _open>\n\t\t\t\t\t\t\tContent\n\t\t\t\t\t\t</KolAccordion>\n\t\t\t\t\t\t<KolAccordion _disabled _label=\"Label (open)\" _open>\n\t\t\t\t\t\t\tContent\n\t\t\t\t\t\t</KolAccordion>\n\t\t\t\t\t</div>\n\t\t\t\t</KolCard>\n\t\t\t\t<KolCard _label=\"Details\" _level={0}>\n\t\t\t\t\t<div className=\"grid gap-4\">\n\t\t\t\t\t\t<KolDetails _label=\"Label\">Content</KolDetails>\n\t\t\t\t\t\t<KolDetails _disabled _label=\"Label\">\n\t\t\t\t\t\t\tContent\n\t\t\t\t\t\t</KolDetails>\n\t\t\t\t\t\t<KolDetails _label=\"Label (open)\" _open>\n\t\t\t\t\t\t\tContent\n\t\t\t\t\t\t</KolDetails>\n\t\t\t\t\t\t<KolDetails _disabled _label=\"Label (open)\" _open>\n\t\t\t\t\t\t\tContent\n\t\t\t\t\t\t</KolDetails>\n\t\t\t\t\t</div>\n\t\t\t\t</KolCard>\n\t\t\t\t{[KolInputCheckbox, KolInputColor, KolInputDate, KolInputEmail, KolInputFile, KolInputNumber, KolInputPassword, KolInputRange, KolInputText].map(\n\t\t\t\t\t(Input) => {\n\t\t\t\t\t\tconst render = (\n\t\t\t\t\t\t\tInput as typeof KolInputCheckbox & {\n\t\t\t\t\t\t\t\trender: { displayName: string };\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t).render;\n\t\t\t\t\t\tconst name = render.displayName;\n\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t<KolCard key={name} _label={name} _level={0}>\n\t\t\t\t\t\t\t\t<div className=\"grid gap-4\">\n\t\t\t\t\t\t\t\t\t<Input _label=\"Label\" />\n\t\t\t\t\t\t\t\t\t<Input _disabled _label=\"Label\" />\n\t\t\t\t\t\t\t\t\t<Input _hideLabel _label=\"Label\" />\n\t\t\t\t\t\t\t\t\t<Input _disabled _hideLabel _label=\"Label\" />\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</KolCard>\n\t\t\t\t\t\t);\n\t\t\t\t\t},\n\t\t\t\t)}\n\t\t\t\t{[KolInputRadio, KolSelect].map((Input) => {\n\t\t\t\t\tconst render = (\n\t\t\t\t\t\tInput as typeof KolInputRadio & {\n\t\t\t\t\t\t\trender: { displayName: string };\n\t\t\t\t\t\t}\n\t\t\t\t\t).render;\n\t\t\t\t\tconst name = render.displayName;\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<KolCard key={name} _label={name} _level={0}>\n\t\t\t\t\t\t\t<div className=\"grid gap-4\">\n\t\t\t\t\t\t\t\t<Input _label=\"Label\" _options={OPTIONS} />\n\t\t\t\t\t\t\t\t<Input _disabled _label=\"Label\" _options={OPTIONS} />\n\t\t\t\t\t\t\t\t<Input _hideLabel _label=\"Label\" _options={OPTIONS} />\n\t\t\t\t\t\t\t\t<Input _disabled _hideLabel _label=\"Label\" _options={OPTIONS} />\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</KolCard>\n\t\t\t\t\t);\n\t\t\t\t})}\n\t\t\t\t<KolCard _label=\"KolTextarea\" _level={0}>\n\t\t\t\t\t<div className=\"grid gap-4\">\n\t\t\t\t\t\t<KolTextarea _label=\"Label\" _rows={3} />\n\t\t\t\t\t\t<KolTextarea _disabled _label=\"Label\" _rows={3} />\n\t\t\t\t\t\t<KolTextarea _hideLabel _label=\"Label\" _rows={3} />\n\t\t\t\t\t\t<KolTextarea _disabled _hideLabel _label=\"Label\" _rows={3} />\n\t\t\t\t\t</div>\n\t\t\t\t</KolCard>\n\t\t\t</div>\n\t\t</>\n\t);\n};\n",
|
|
2137
2153
|
"kind": "scenario"
|
|
2138
2154
|
},
|
|
2139
2155
|
{
|
|
@@ -2197,7 +2213,7 @@
|
|
|
2197
2213
|
"group": "scenarios",
|
|
2198
2214
|
"name": "same-height-of-all-interactive-elements",
|
|
2199
2215
|
"path": "packages/samples/react/src/scenarios/same-height-of-all-interactive-elements.tsx",
|
|
2200
|
-
"code": "import {\n\tKolButton,\n\tKolCombobox,\n\tKolInputColor,\n\tKolInputDate,\n\tKolInputEmail,\n\tKolInputFile,\n\tKolInputNumber,\n\tKolInputPassword,\n\tKolInputRange,\n\tKolInputText,\n\tKolLinkButton,\n\tKolSelect,\n\tKolSingleSelect,\n\tKolTextarea,\n} from '@public-ui/react-v19';\nimport type { FC } from 'react';\nimport React from 'react';\nimport { SampleDescription } from '../components/SampleDescription';\nimport {
|
|
2216
|
+
"code": "import {\n\tKolButton,\n\tKolCombobox,\n\tKolInputColor,\n\tKolInputDate,\n\tKolInputEmail,\n\tKolInputFile,\n\tKolInputNumber,\n\tKolInputPassword,\n\tKolInputRange,\n\tKolInputText,\n\tKolLinkButton,\n\tKolSelect,\n\tKolSingleSelect,\n\tKolTextarea,\n} from '@public-ui/react-v19';\nimport type { FC } from 'react';\nimport React from 'react';\nimport { SampleDescription } from '../components/SampleDescription';\nimport { useAlert } from '../hooks/useAlert';\n\nexport const SameHeightOfAllInteractiveElements: FC = () => {\n\tconst { dummyClickEventHandler } = useAlert();\n\n\tconst dummyEventHandler = {\n\t\tonClick: dummyClickEventHandler,\n\t};\n\n\treturn (\n\t\t<>\n\t\t\t<SampleDescription>\n\t\t\t\t<p>\n\t\t\t\t\tAll interactive elements, such as buttons and input fields, should have the same height to ensure a consistent and visually balanced user interface.\n\t\t\t\t</p>\n\t\t\t</SampleDescription>\n\t\t\t<div className=\"w-full flex flex-wrap gap-4\">\n\t\t\t\t<KolButton _icons=\"kolicon-house\" _label=\"Button\" _on={dummyEventHandler} />\n\t\t\t\t<KolButton _hideLabel _icons=\"kolicon-house\" _label=\"Button\" _on={dummyEventHandler} />\n\t\t\t\t<KolLinkButton _href=\"#\" _icons=\"kolicon-house\" _label=\"Link-Button\" _on={dummyEventHandler} />\n\t\t\t\t<KolLinkButton _hideLabel _href=\"#\" _icons=\"kolicon-house\" _label=\"Link-Button\" _on={dummyEventHandler} />\n\t\t\t\t<KolCombobox _hideLabel _icons=\"kolicon-house\" _label=\"Combobox\" _suggestions={[]} />\n\t\t\t\t<KolInputColor\n\t\t\t\t\t_hideLabel\n\t\t\t\t\t_icons={{\n\t\t\t\t\t\tleft: 'kolicon-house',\n\t\t\t\t\t}}\n\t\t\t\t\t_label=\"Input-Color\"\n\t\t\t\t/>\n\t\t\t\t<KolInputFile _hideLabel _icons=\"kolicon-house\" _label=\"Input-File\" />\n\t\t\t\t<KolInputDate _hideLabel _icons=\"kolicon-house\" _label=\"Input-Date\" />\n\t\t\t\t<KolInputEmail _hideLabel _icons=\"kolicon-house\" _label=\"Input-Email\" />\n\t\t\t\t<KolInputNumber _hideLabel _icons=\"kolicon-house\" _label=\"Input-Number\" />\n\t\t\t\t<KolInputPassword _hideLabel _icons=\"kolicon-house\" _label=\"Input-Password\" />\n\t\t\t\t<KolInputRange _hideLabel _icons=\"kolicon-house\" _label=\"Input-Range\" />\n\t\t\t\t<KolInputText _hideLabel _icons=\"kolicon-house\" _label=\"Input-Text\" />\n\t\t\t\t<KolSelect _hideLabel _icons=\"kolicon-house\" _label=\"Select\" _options={[]} />\n\t\t\t\t<KolSingleSelect _hideLabel _icons=\"kolicon-house\" _label=\"Single Select\" _options={[]} />\n\t\t\t\t<KolTextarea _hideLabel _icons=\"kolicon-house\" _label=\"Textarea\" />\n\t\t\t</div>\n\t\t</>\n\t);\n};\n",
|
|
2201
2217
|
"kind": "scenario"
|
|
2202
2218
|
},
|
|
2203
2219
|
{
|
|
@@ -2205,7 +2221,7 @@
|
|
|
2205
2221
|
"group": "scenarios",
|
|
2206
2222
|
"name": "sample-form-with-validation",
|
|
2207
2223
|
"path": "packages/samples/react/src/scenarios/sample-form-with-validation.tsx",
|
|
2208
|
-
"code": "import { zodResolver } from '@hookform/resolvers/zod';\nimport {\n\tKolComboboxController,\n\tKolInputCheckboxController,\n\tKolInputColorController,\n\tKolInputDateController,\n\tKolInputEmailController,\n\tKolInputNumberController,\n\tKolInputPasswordController,\n\tKolInputRadioController,\n\tKolInputRangeController,\n\tKolInputTextController,\n\tKolSelectController,\n\tKolSingleSelectController,\n\tKolTextareaController,\n} from '@public-ui/react-hook-form-adapter';\nimport { KolAlert, KolButton, KolHeading, KolLink } from '@public-ui/react-v19';\nimport React from 'react';\nimport type { FieldError } from 'react-hook-form';\nimport { useForm } from 'react-hook-form';\nimport { z } from 'zod';\n\nimport { SampleDescription } from '../components/SampleDescription';\nimport {
|
|
2224
|
+
"code": "import { zodResolver } from '@hookform/resolvers/zod';\nimport {\n\tKolComboboxController,\n\tKolInputCheckboxController,\n\tKolInputColorController,\n\tKolInputDateController,\n\tKolInputEmailController,\n\tKolInputNumberController,\n\tKolInputPasswordController,\n\tKolInputRadioController,\n\tKolInputRangeController,\n\tKolInputTextController,\n\tKolSelectController,\n\tKolSingleSelectController,\n\tKolTextareaController,\n} from '@public-ui/react-hook-form-adapter';\nimport { KolAlert, KolButton, KolHeading, KolLink } from '@public-ui/react-v19';\nimport React from 'react';\nimport type { FieldError } from 'react-hook-form';\nimport { useForm } from 'react-hook-form';\nimport { z } from 'zod';\n\nimport { SampleDescription } from '../components/SampleDescription';\nimport { useAlert } from '../hooks/useAlert';\nimport { COUNTRY_SUGGESTIONS } from '../shares/country';\n\nconst formSchema = z.object({\n\tdate: z.preprocess(\n\t\t(val) => (typeof val === 'string' || val instanceof Date ? new Date(val) : undefined),\n\t\tz.date({ message: 'Date is required' }).refine((d) => !isNaN(d.getTime()), { message: 'Invalid date' }),\n\t),\n\n\ttext: z.string({ message: 'Please enter text.' }).min(10, 'Text must be at least 10 characters long.'),\n\temail: z.string({ message: 'Please enter your email.' }).min(1, 'Please enter your email.').email('Invalid email address.'),\n\tpassword: z\n\t\t.string({ message: 'Please enter a password.' })\n\t\t.min(8, 'Password must be at least 8 characters.')\n\t\t.regex(/[A-Z]/, 'Password must include at least one uppercase letter.')\n\t\t.regex(/[0-9]/, 'Password must include at least one number.'),\n\trange: z.number({ message: 'Please select a range.' }).min(30, 'Minimum value is 30.'),\n\tnumber: z.number({ message: 'Please enter a number.' }).min(1, 'Minimum is 1.').max(10, 'Maximum is 10.'),\n\tcheckbox: z.boolean().refine((val: boolean) => val === true, {\n\t\tmessage: 'You must accept the terms and conditions.',\n\t}),\n\n\tradio: z.string({ message: 'Please select a gender.' }).min(1, 'Please select a gender.'),\n\tcolor: z.string({ message: 'Please select a color.' }).min(1, 'Please select a color.'),\n\tselect: z.string({ message: 'Please select a value.' }).min(1, 'Please select a value.'),\n\tsingleSelect: z.string({ message: 'Please select a single option.' }).min(1, 'Please select a single option.'),\n\tcombobox: z.string({ message: 'Please select a country.' }).min(1, 'Please select a country.'),\n\ttextarea: z.string({ message: 'Please enter a message.' }).min(1, 'Please enter a message.'),\n});\n\nexport const SampleFormWithValidation: React.FC = () => {\n\tconst { dummyClickEventHandler } = useAlert();\n\tconst {\n\t\thandleSubmit,\n\t\tformState: { errors },\n\t\treset,\n\t\tcontrol,\n\t} = useForm({\n\t\tmode: 'onBlur',\n\t\treValidateMode: 'onChange',\n\t\tresolver: zodResolver(formSchema),\n\t\tdefaultValues: {\n\t\t\trange: 30,\n\t\t\tnumber: 5,\n\t\t},\n\t});\n\n\tconst onReset = () => {\n\t\treset(undefined, {\n\t\t\tkeepErrors: false,\n\t\t\tkeepTouched: false,\n\t\t\tkeepDirty: false,\n\t\t});\n\t};\n\n\tconst allErrors = Object.entries(errors)\n\t\t.map(([key, value]) => [key, (value as FieldError).message] as const)\n\t\t.filter(([, msg]) => Boolean(msg));\n\n\treturn (\n\t\t<section className=\"w-full max-w-3xl mx-auto p-6\">\n\t\t\t<KolHeading _level={2} _label=\"Sample Form with Validation (Zod)\" />\n\t\t\t<SampleDescription>\n\t\t\t\t<p>\n\t\t\t\t\tThis example shows validation with <code>react-hook-form</code>, <code>Zod</code>, and an error list.\n\t\t\t\t</p>\n\t\t\t</SampleDescription>\n\n\t\t\t{allErrors.length > 0 && (\n\t\t\t\t<KolAlert _type=\"error\" _label=\"Please fix the following:\" _alert _variant=\"card\">\n\t\t\t\t\t<ul className=\"list-disc pl-5\">\n\t\t\t\t\t\t{allErrors.map(([key, msg], i) => (\n\t\t\t\t\t\t\t<li key={i}>\n\t\t\t\t\t\t\t\t<KolLink\n\t\t\t\t\t\t\t\t\t_label={msg}\n\t\t\t\t\t\t\t\t\t_href={`#field-${key}`}\n\t\t\t\t\t\t\t\t\t_on={{\n\t\t\t\t\t\t\t\t\t\tonClick: (e: Event) => {\n\t\t\t\t\t\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t\t\t\t\t\t\tconst input = document.getElementById(`field-${key}`);\n\t\t\t\t\t\t\t\t\t\t\tinput?.focus();\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t</li>\n\t\t\t\t\t\t))}\n\t\t\t\t\t</ul>\n\t\t\t\t</KolAlert>\n\t\t\t)}\n\n\t\t\t<form onSubmit={handleSubmit(dummyClickEventHandler)} noValidate className=\"grid gap-4 mt-6\">\n\t\t\t\t<KolInputDateController control={control as any} name=\"date\" _label=\"Date\" />\n\t\t\t\t<KolInputTextController control={control as any} name=\"text\" _label=\"Text (≥ 10 chars)\" />\n\t\t\t\t<KolInputEmailController control={control as any} name=\"email\" _label=\"Email\" />\n\t\t\t\t<KolInputPasswordController control={control as any} name=\"password\" _label=\"Password\" />\n\t\t\t\t<KolInputRangeController control={control as any} name=\"range\" _label=\"Range (≥ 30)\" _min={0} _max={100} />\n\t\t\t\t<KolInputNumberController control={control as any} name=\"number\" _label=\"Number (1 – 10)\" />\n\t\t\t\t<KolInputCheckboxController control={control as any} name=\"checkbox\" _label=\"Accept terms\" />\n\t\t\t\t<KolInputRadioController\n\t\t\t\t\tcontrol={control as any}\n\t\t\t\t\tname=\"radio\"\n\t\t\t\t\t_label=\"Gender\"\n\t\t\t\t\t_options={[\n\t\t\t\t\t\t{ label: 'Female', value: 'f' },\n\t\t\t\t\t\t{ label: 'Male', value: 'm' },\n\t\t\t\t\t]}\n\t\t\t\t/>\n\t\t\t\t<KolInputColorController control={control as any} name=\"color\" _label=\"Favorite Color\" />\n\t\t\t\t<KolSelectController\n\t\t\t\t\tcontrol={control as any}\n\t\t\t\t\tname=\"select\"\n\t\t\t\t\t_label=\"Select\"\n\t\t\t\t\t_options={[\n\t\t\t\t\t\t{ label: 'Option A', value: 'A' },\n\t\t\t\t\t\t{ label: 'Option B', value: 'B' },\n\t\t\t\t\t]}\n\t\t\t\t/>\n\t\t\t\t<KolSingleSelectController\n\t\t\t\t\tcontrol={control as any}\n\t\t\t\t\tname=\"singleSelect\"\n\t\t\t\t\t_label=\"Single Select\"\n\t\t\t\t\t_options={[\n\t\t\t\t\t\t{ label: 'Option A', value: 'A' },\n\t\t\t\t\t\t{ label: 'Option B', value: 'B' },\n\t\t\t\t\t]}\n\t\t\t\t/>\n\t\t\t\t<KolComboboxController control={control as any} name=\"combobox\" _label=\"Country\" _suggestions={COUNTRY_SUGGESTIONS} />\n\t\t\t\t<KolTextareaController control={control as any} name=\"textarea\" _label=\"Message\" _rows={4} />\n\n\t\t\t\t<div className=\"flex gap-4 mt-4\">\n\t\t\t\t\t<KolButton _label=\"Submit\" _type=\"submit\" _variant=\"primary\" />\n\t\t\t\t\t<KolButton _label=\"Reset\" _type=\"reset\" onClick={onReset} />\n\t\t\t\t</div>\n\t\t\t</form>\n\t\t</section>\n\t);\n};\n",
|
|
2209
2225
|
"kind": "scenario"
|
|
2210
2226
|
},
|
|
2211
2227
|
{
|