<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Sachin Dilshan</title>
    <description>The latest articles on Forem by Sachin Dilshan (@toozuuu).</description>
    <link>https://forem.com/toozuuu</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3441219%2F5895d34e-5bab-43be-8234-c4620300c9fe.jpg</url>
      <title>Forem: Sachin Dilshan</title>
      <link>https://forem.com/toozuuu</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/toozuuu"/>
    <language>en</language>
    <item>
      <title>Type-Safe Design Tokens in Vue: Introducing TokiForge v1.1.0</title>
      <dc:creator>Sachin Dilshan</dc:creator>
      <pubDate>Tue, 11 Nov 2025 11:51:30 +0000</pubDate>
      <link>https://forem.com/toozuuu/type-safe-design-tokens-in-vue-introducing-tokiforge-v110-5ca4</link>
      <guid>https://forem.com/toozuuu/type-safe-design-tokens-in-vue-introducing-tokiforge-v110-5ca4</guid>
      <description>&lt;p&gt;If you've ever worked with design tokens in Vue, you know the pain of losing type safety. You define your tokens with a specific structure, but when you access them in components, TypeScript treats them as a generic &lt;code&gt;DesignTokens&lt;/code&gt; type. No autocomplete, no type checking, and plenty of opportunities for typos.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TokiForge v1.1.0&lt;/strong&gt; solves this problem by introducing type-safe token access for Vue developers. In this post, we'll explore how this feature works, why it matters, and how to use it in your projects.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem: Losing Type Information
&lt;/h2&gt;

&lt;p&gt;Before v1.1.0, when you used &lt;code&gt;useTheme()&lt;/code&gt; in Vue, you'd get back a &lt;code&gt;ComputedRef&amp;lt;DesignTokens&amp;gt;&lt;/code&gt;. While this works, it's not very helpful:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Before v1.1.0&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;tokens&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useTheme&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// TypeScript only knows it's DesignTokens&lt;/span&gt;
&lt;span class="c1"&gt;// No autocomplete for token paths&lt;/span&gt;
&lt;span class="c1"&gt;// No type checking for token structure&lt;/span&gt;
&lt;span class="nx"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;color&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;primary&lt;/span&gt; &lt;span class="c1"&gt;// ❌ TypeScript doesn't know if this exists&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;❌ No IntelliSense/autocomplete&lt;/li&gt;
&lt;li&gt;❌ No compile-time type checking&lt;/li&gt;
&lt;li&gt;❌ Easy to make typos in token paths&lt;/li&gt;
&lt;li&gt;❌ No refactoring support&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Solution: Generic Type Parameters
&lt;/h2&gt;

&lt;p&gt;TokiForge v1.1.0 introduces generic type support to &lt;code&gt;useTheme()&lt;/code&gt; and &lt;code&gt;provideTheme()&lt;/code&gt;. Now you can specify your exact token type and get full type safety:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// v1.1.0 - Type-safe!&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;tokens&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useTheme&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;MyDesignTokens&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// Full autocomplete and type checking! ✅&lt;/span&gt;
&lt;span class="nx"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;color&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;primary&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="c1"&gt;// TypeScript knows this exists&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Getting Started
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Installation
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; @tokiforge/core @tokiforge/vue
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Define Your Token Type
&lt;/h3&gt;

&lt;p&gt;First, define your token structure as a TypeScript interface:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;DesignTokens&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;TokenValue&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@tokiforge/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;MyDesignTokens&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;DesignTokens&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;primary&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;TokenValue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;secondary&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;TokenValue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;TokenValue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nl"&gt;muted&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;TokenValue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="nl"&gt;radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;sm&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;TokenValue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;md&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;TokenValue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;lg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;TokenValue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="nl"&gt;spacing&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;xs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;TokenValue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;sm&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;TokenValue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;md&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;TokenValue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;lg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;TokenValue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Create Your Tokens
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;lightTokens&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;MyDesignTokens&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;primary&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#7C3AED&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;color&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;secondary&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#06B6D4&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;color&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#FFFFFF&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;color&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="na"&gt;muted&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#F9FAFB&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;color&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;sm&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;4px&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dimension&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;md&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;8px&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dimension&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;lg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;12px&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dimension&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;spacing&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;xs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;4px&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dimension&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;sm&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;8px&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dimension&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;md&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;16px&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dimension&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;lg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;24px&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dimension&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;darkTokens&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;MyDesignTokens&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;primary&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#A78BFA&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;color&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;secondary&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#22D3EE&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;color&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#0F172A&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;color&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="na"&gt;muted&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#1E293B&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;color&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;sm&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;4px&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dimension&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;md&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;8px&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dimension&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;lg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;12px&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dimension&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;spacing&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;xs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;4px&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dimension&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;sm&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;8px&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dimension&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;md&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;16px&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dimension&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;lg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;24px&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dimension&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Provide Theme with Type Safety
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt; &lt;span class="na"&gt;setup&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"ts"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;provideTheme&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@tokiforge/vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;themeConfig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;themes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;light&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;lightTokens&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dark&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;darkTokens&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;defaultTheme&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;light&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// Type is automatically inferred from config!&lt;/span&gt;
&lt;span class="nf"&gt;provideTheme&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;themeConfig&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Use Theme with Type Safety
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt; &lt;span class="na"&gt;setup&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"ts"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useTheme&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@tokiforge/vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Specify your token type for full type safety&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setTheme&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useTheme&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;MyDesignTokens&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// Now you get full autocomplete! 🎉&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;primaryColor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;color&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;primary&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;borderRadius&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;radius&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;spacing&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;spacing&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;md&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt;
      &lt;span class="na"&gt;:style=&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;{
        backgroundColor: tokens.value.color.primary.value,
        borderRadius: tokens.value.radius.lg.value,
        padding: tokens.value.spacing.md.value,
      }"
      @click="setTheme('dark')"
    &amp;gt;
      Switch Theme
    &lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Real-World Example
&lt;/h2&gt;

&lt;p&gt;Here's a complete example showing how type-safe tokens work in a real component:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"card"&lt;/span&gt; &lt;span class="na"&gt;:style=&lt;/span&gt;&lt;span class="s"&gt;"cardStyles"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;h2&lt;/span&gt; &lt;span class="na"&gt;:style=&lt;/span&gt;&lt;span class="s"&gt;"headingStyles"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Type-Safe Tokens&lt;span class="nt"&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;:style=&lt;/span&gt;&lt;span class="s"&gt;"textStyles"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      This component uses type-safe design tokens with full IntelliSense support.
    &lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;:style=&lt;/span&gt;&lt;span class="s"&gt;"buttonStyles"&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;click=&lt;/span&gt;&lt;span class="s"&gt;"toggleTheme"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      Current Theme: &lt;span class="si"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;theme&lt;/span&gt; &lt;span class="si"&gt;}}&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt; &lt;span class="na"&gt;setup&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"ts"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;computed&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useTheme&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@tokiforge/vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;DesignTokens&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;TokenValue&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@tokiforge/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;AppDesignTokens&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;DesignTokens&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;primary&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;TokenValue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;secondary&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;TokenValue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;primary&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;TokenValue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nl"&gt;secondary&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;TokenValue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;TokenValue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nl"&gt;card&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;TokenValue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="nl"&gt;radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;sm&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;TokenValue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;md&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;TokenValue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;lg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;TokenValue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="nl"&gt;spacing&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;sm&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;TokenValue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;md&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;TokenValue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;lg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;TokenValue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setTheme&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useTheme&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;AppDesignTokens&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cardStyles&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;computed&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;backgroundColor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;color&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;background&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;card&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;borderRadius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;radius&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;md&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;spacing&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}));&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;headingStyles&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;computed&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;color&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;primary&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;marginBottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;spacing&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;md&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}));&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;textStyles&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;computed&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;color&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;secondary&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;marginBottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;spacing&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;md&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}));&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;buttonStyles&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;computed&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;backgroundColor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;color&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;primary&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#FFFFFF&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;borderRadius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;radius&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;spacing&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;spacing&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;md&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;none&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pointer&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}));&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;toggleTheme&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;setTheme&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;light&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dark&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;light&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Benefits of Type-Safe Tokens
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. &lt;strong&gt;IntelliSense/Autocomplete&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Your IDE now knows exactly what tokens are available:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;color&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="c1"&gt;// IDE suggests: primary, secondary, text, background&lt;/span&gt;
&lt;span class="nx"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;radius&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="c1"&gt;// IDE suggests: sm, md, lg&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. &lt;strong&gt;Compile-Time Type Checking&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;TypeScript will catch errors before runtime:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ❌ TypeScript error: Property 'invalid' does not exist&lt;/span&gt;
&lt;span class="nx"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;color&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;invalid&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// ✅ TypeScript knows this is valid&lt;/span&gt;
&lt;span class="nx"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;color&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;primary&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. &lt;strong&gt;Refactoring Support&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;When you rename tokens, your IDE can refactor all usages automatically.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. &lt;strong&gt;Better Documentation&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The type definition serves as documentation for your token structure.&lt;/p&gt;

&lt;h2&gt;
  
  
  Type Inference
&lt;/h2&gt;

&lt;p&gt;You don't always need to explicitly specify the type. TokiForge can infer it from your config:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;themes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;light&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;lightTokens&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dark&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;darkTokens&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;defaultTheme&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;light&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// Type is automatically inferred!&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;provideTheme&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// context.tokens is now typed based on your token structure&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Backward Compatibility
&lt;/h2&gt;

&lt;p&gt;All existing code continues to work without changes. If you don't specify a type parameter, it defaults to &lt;code&gt;DesignTokens&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Still works - defaults to DesignTokens&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;tokens&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useTheme&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This means you can migrate gradually, adding type safety where it matters most.&lt;/p&gt;

&lt;h2&gt;
  
  
  Migration Guide
&lt;/h2&gt;

&lt;p&gt;Migrating to type-safe tokens is straightforward:&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Define Your Token Type
&lt;/h3&gt;

&lt;p&gt;Create an interface that extends &lt;code&gt;DesignTokens&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;MyDesignTokens&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;DesignTokens&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Your token structure&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 2: Update Your Token Definitions
&lt;/h3&gt;

&lt;p&gt;Add type annotations to your token objects:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;lightTokens&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;MyDesignTokens&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Your tokens&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 3: Use Generic Type Parameter
&lt;/h3&gt;

&lt;p&gt;Update your &lt;code&gt;useTheme()&lt;/code&gt; calls:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Before&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;tokens&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useTheme&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// After&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;tokens&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useTheme&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;MyDesignTokens&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it! Your code now has full type safety.&lt;/p&gt;

&lt;h2&gt;
  
  
  Advanced Usage
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Extracting Token Types
&lt;/h3&gt;

&lt;p&gt;You can extract the token type from your config:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ExtractTokenType&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@tokiforge/vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;themes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;MyDesignTokens&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;defaultTheme&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;InferredTokens&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ExtractTokenType&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Config&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;ThemeConfig&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Multiple Token Types
&lt;/h3&gt;

&lt;p&gt;If you have different token structures for different parts of your app:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;ComponentTokens&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;DesignTokens&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;button&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;primary&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;TokenValue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;secondary&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;TokenValue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;tokens&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useTheme&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ComponentTokens&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Performance
&lt;/h2&gt;

&lt;p&gt;Type safety comes with &lt;strong&gt;zero runtime overhead&lt;/strong&gt;. The generic types are purely compile-time features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ No runtime performance impact&lt;/li&gt;
&lt;li&gt;✅ Still &amp;lt;3KB gzipped&lt;/li&gt;
&lt;li&gt;✅ Uses CSS variables for instant theme switching&lt;/li&gt;
&lt;li&gt;✅ SSR-friendly&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What's Next?
&lt;/h2&gt;

&lt;p&gt;Type-safe token access is currently available for Vue. We're planning to extend this to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;React&lt;/strong&gt;: Type-safe &lt;code&gt;useTheme()&lt;/code&gt; hook&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Svelte&lt;/strong&gt;: Type-safe &lt;code&gt;createThemeStore()&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Angular&lt;/strong&gt;: Type-safe theme service&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you're interested in contributing, we'd love your help! Check out our &lt;a href="https://github.com/TokiForge/tokiforge/blob/main/ROADMAP.md" rel="noopener noreferrer"&gt;roadmap&lt;/a&gt; for more details.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Type-safe design tokens in TokiForge v1.1.0 bring the full power of TypeScript to your design system. With autocomplete, type checking, and better developer experience, building type-safe design systems has never been easier.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Try it out today:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; @tokiforge/core @tokiforge/vue
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Resources:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;📚 &lt;a href="https://tokiforge.github.io/tokiforge" rel="noopener noreferrer"&gt;Documentation&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;💻 &lt;a href="https://github.com/TokiForge/tokiforge" rel="noopener noreferrer"&gt;GitHub Repository&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🐛 &lt;a href="https://github.com/TokiForge/tokiforge/issues" rel="noopener noreferrer"&gt;Report Issues&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;💬 &lt;a href="https://github.com/TokiForge/tokiforge/discussions" rel="noopener noreferrer"&gt;Discussions&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Have questions or feedback? Drop a comment below or open an issue on GitHub!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>vue</category>
      <category>typescript</category>
      <category>frontend</category>
    </item>
    <item>
      <title>Introducing TokiForge: A Framework-Agnostic Design Token Engine with Runtime Theme Switching</title>
      <dc:creator>Sachin Dilshan</dc:creator>
      <pubDate>Thu, 06 Nov 2025 09:15:18 +0000</pubDate>
      <link>https://forem.com/toozuuu/introducing-tokiforge-a-framework-agnostic-design-token-engine-with-runtime-theme-switching-2e72</link>
      <guid>https://forem.com/toozuuu/introducing-tokiforge-a-framework-agnostic-design-token-engine-with-runtime-theme-switching-2e72</guid>
      <description>&lt;p&gt;&lt;strong&gt;Introducing TokiForge: A Framework-Agnostic Design Token Engine with Runtime Theme Switching&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Problem&lt;/strong&gt;&lt;br&gt;
As frontend developers, we've all been there. You're working on a React project, and you need a theming solution. So you set up styled-components or Theme UI. Then you start a Vue project, and you need a different solution. Then Svelte, and another approach. Before you know it, you're maintaining three different theming systems, each with its own quirks and limitations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The pain points&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Different solutions for each framework&lt;/li&gt;
&lt;li&gt;Theme switching requires reloads or rebuilds&lt;/li&gt;
&lt;li&gt;Inconsistent token management across projects&lt;/li&gt;
&lt;li&gt;Time wasted on setup and configuration&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;The Solution: TokiForge&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We built &lt;strong&gt;TokiForge&lt;/strong&gt; - a framework-agnostic design token and theming engine that works with React, Vue, Svelte, Angular, and any JavaScript framework. One tool, multiple frameworks, zero friction.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What Makes TokiForge Different?&lt;/strong&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  Framework-Agnostic Core
&lt;/h1&gt;

&lt;p&gt;Unlike framework-specific solutions, TokiForge's core works everywhere:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;typescript
import { ThemeRuntime } from '@tokiforge/core';

const runtime = new ThemeRuntime({
  themes: [
    { name: 'light', tokens: lightTokens },
    { name: 'dark', tokens: darkTokens }
  ],
  defaultTheme: 'light'
});

runtime.init();
runtime.applyTheme('dark'); // Switch instantly!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Runtime Theme Switching
&lt;/h1&gt;

&lt;p&gt;Switch themes without page reloads or rebuilds. Perfect for light/dark mode, multi-brand applications, or dynamic theming.&lt;/p&gt;

&lt;h1&gt;
  
  
  Framework Adapters
&lt;/h1&gt;

&lt;p&gt;While the core works everywhere, we provide dedicated adapters for popular frameworks:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;React&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;tsx
import { ThemeProvider, useTheme } from '@tokiforge/react';

function App() {
  return (
    &amp;lt;ThemeProvider config={themeConfig}&amp;gt;
      &amp;lt;MyComponent /&amp;gt;
    &amp;lt;/ThemeProvider&amp;gt;
  );
}

function MyComponent() {
  const { theme, setTheme } = useTheme();
  return &amp;lt;button onClick={() =&amp;gt; setTheme('dark')}&amp;gt;Dark Mode&amp;lt;/button&amp;gt;;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Vue&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;vue
&amp;lt;script setup&amp;gt;
import { useTheme } from '@tokiforge/vue';

const { theme, setTheme } = useTheme(config);
&amp;lt;/script&amp;gt;

&amp;lt;template&amp;gt;
  &amp;lt;button @click="setTheme('dark')"&amp;gt;Switch Theme&amp;lt;/button&amp;gt;
&amp;lt;/template&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Svelte&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;svelte
&amp;lt;script&amp;gt;
  import { createThemeStore } from '@tokiforge/svelte';

  const theme = createThemeStore(config);
&amp;lt;/script&amp;gt;

&amp;lt;button on:click={() =&amp;gt; theme.setTheme('dark')}&amp;gt;
  Switch Theme
&amp;lt;/button&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Key Features&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;✨ &lt;strong&gt;Runtime Theme Switching&lt;/strong&gt; - No reloads or rebuilds needed&lt;br&gt;
🎨 &lt;strong&gt;Framework-Agnostic&lt;/strong&gt; - Works with React, Vue, Svelte, Angular, and vanilla JS&lt;br&gt;
🔧 &lt;strong&gt;CLI Tool&lt;/strong&gt; - Get started in seconds&lt;br&gt;
🧪 &lt;strong&gt;Production Ready&lt;/strong&gt; - 58 tests, 100% passing, TypeScript support&lt;br&gt;
📦 &lt;strong&gt;Multiple Export Formats&lt;/strong&gt; - CSS, SCSS, JavaScript, TypeScript, or JSON&lt;br&gt;
🎯 &lt;strong&gt;Token Parsing&lt;/strong&gt; - Supports JSON and YAML&lt;br&gt;
🔒 &lt;strong&gt;Type Safe&lt;/strong&gt; - Full TypeScript definitions&lt;br&gt;
♿ &lt;strong&gt;Accessibility&lt;/strong&gt; - Built-in color contrast checking&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Quick Start&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Installation&lt;/p&gt;
&lt;h1&gt;
  
  
  Install CLI globally
&lt;/h1&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install -g tokiforge-cli

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h1&gt;
  
  
  Or install packages directly
&lt;/h1&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install @tokiforge/core
npm install @tokiforge/react  # or vue, svelte
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Initialize a Project
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;tokiforge init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This creates:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;tokens.json&lt;/code&gt; - Your design tokens&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;tokiforge.config.json&lt;/code&gt; - Configuration file&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Build Tokens
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;tokiforge build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Generates token exports in multiple formats based on your config.&lt;/p&gt;
&lt;h3&gt;
  
  
  Use in Your App
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;React Example&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;tsx
import { ThemeProvider, useTheme } from '@tokiforge/react';

const themeConfig = {
  themes: [
    {
      name: 'light',
      tokens: {
        color: {
          primary: { value: '#7C3AED', type: 'color' },
          background: { value: '#FFFFFF', type: 'color' }
        }
      }
    },
    {
      name: 'dark',
      tokens: {
        color: {
          primary: { value: '#A78BFA', type: 'color' },
          background: { value: '#1F2937', type: 'color' }
        }
      }
    }
  ],
  defaultTheme: 'light'
};

function App() {
  return (
    &amp;lt;ThemeProvider config={themeConfig}&amp;gt;
      &amp;lt;ThemeSwitcher /&amp;gt;
    &amp;lt;/ThemeProvider&amp;gt;
  );
}

function ThemeSwitcher() {
  const { theme, setTheme, tokens } = useTheme();

  return (
    &amp;lt;div style={{ 
      background: tokens.color.background.value,
      color: tokens.color.primary.value 
    }}&amp;gt;
      &amp;lt;p&amp;gt;Current theme: {theme}&amp;lt;/p&amp;gt;
      &amp;lt;button onClick={() =&amp;gt; setTheme(theme === 'light' ? 'dark' : 'light')}&amp;gt;
        Toggle Theme
      &amp;lt;/button&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Real-World Use Cases&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Design Systems&lt;/strong&gt; - Manage tokens across multiple projects&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multi-Theme Apps&lt;/strong&gt; - Light/dark mode, brand variations&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Runtime Theming&lt;/strong&gt; - Switch themes based on user preferences&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Token Validation&lt;/strong&gt; - Ensure consistency across your codebase&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Accessibility&lt;/strong&gt; - Built-in color contrast checking&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;What's Included&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ Token parser (JSON/YAML support)&lt;/li&gt;
&lt;li&gt;✅ Token exporter (CSS, SCSS, JS, TS, JSON)&lt;/li&gt;
&lt;li&gt;✅ Theme runtime engine&lt;/li&gt;
&lt;li&gt;✅ Color utilities with accessibility checking&lt;/li&gt;
&lt;li&gt;✅ Framework adapters (React, Vue, Svelte)&lt;/li&gt;
&lt;li&gt;✅ CLI tool for development workflow&lt;/li&gt;
&lt;li&gt;✅ Comprehensive test suite (58 tests)&lt;/li&gt;
&lt;li&gt;✅ Full TypeScript support&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Production Ready&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;TokiForge is fully tested and production-ready:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;58 tests&lt;/strong&gt; covering all core functionality&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;100% passing&lt;/strong&gt; test suite&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;TypeScript&lt;/strong&gt; support with full type definitions&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Optimized&lt;/strong&gt; bundle size (&amp;lt;3KB gzipped)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SSR-safe&lt;/strong&gt; for Next.js, Nuxt, SvelteKit, etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Get Started&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GitHub:&lt;/strong&gt; &lt;a href="https://github.com/TokiForge/tokiforge" rel="noopener noreferrer"&gt;https://github.com/TokiForge/tokiforge&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;API Documentation:&lt;/strong&gt; &lt;a href="https://tokiforge.github.io/tokiforge/" rel="noopener noreferrer"&gt;https://tokiforge.github.io/tokiforge/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;npm:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;@tokiforge/core&lt;/code&gt; - Core engine&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;@tokiforge/react&lt;/code&gt; - React adapter&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;@tokiforge/vue&lt;/code&gt; - Vue adapter&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;@tokiforge/svelte&lt;/code&gt; - Svelte adapter&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;tokiforge-cli&lt;/code&gt; - CLI tool&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Documentation:&lt;/strong&gt; &lt;a href="https://github.com/TokiForge/tokiforge#readme" rel="noopener noreferrer"&gt;https://github.com/TokiForge/tokiforge#readme&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why We Built It&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We were tired of managing different theming solutions for each framework. TokiForge solves this by providing one tool that works everywhere, with runtime theme switching and a great developer experience.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What's Next?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We're open to feedback and contributions! What features would you like to see?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Figma plugin for bidirectional sync&lt;/li&gt;
&lt;li&gt;More framework adapters&lt;/li&gt;
&lt;li&gt;Enhanced CLI features&lt;/li&gt;
&lt;li&gt;Visual token editor&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Try It Now&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install -g tokiforge-cli
tokiforge init
tokiforge build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let us know what you think! 🚀&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; #webdev #javascript #react #vue #svelte #typescript #designtokens #theming #opensource #frontend&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>opensource</category>
      <category>javascript</category>
    </item>
    <item>
      <title>🚀 ngxsmk-datatable v1.7.0 — Enterprise Edition is here!</title>
      <dc:creator>Sachin Dilshan</dc:creator>
      <pubDate>Wed, 29 Oct 2025 09:16:48 +0000</pubDate>
      <link>https://forem.com/toozuuu/ngxsmk-datatable-v170-enterprise-edition-is-here-2hf1</link>
      <guid>https://forem.com/toozuuu/ngxsmk-datatable-v170-enterprise-edition-is-here-2hf1</guid>
      <description>&lt;p&gt;We’re thrilled to announce the release of ngxsmk-datatable v1.7.0, our biggest update yet — introducing the Enterprise Edition, designed for modern data-driven Angular applications.&lt;/p&gt;

&lt;p&gt;✨ What’s New&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;📄 PDF Export (powered by jsPDF)&lt;/li&gt;
&lt;li&gt;🤝 Real-time Collaboration via WebSocket&lt;/li&gt;
&lt;li&gt;📊 Inline Charts &amp;amp; Sparklines&lt;/li&gt;
&lt;li&gt;🎨 Advanced Theming with 11 built-in themes&lt;/li&gt;
&lt;li&gt;🧮 Formula Engine (Excel-style expressions)&lt;/li&gt;
&lt;li&gt;🗂️ Multi-sheet &amp;amp; Multi-view Support&lt;/li&gt;
&lt;li&gt;💾 Data Import Wizard (CSV, Excel, JSON)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All new features are opt-in, fully backward compatible, and built for enterprise-grade performance.&lt;/p&gt;

&lt;p&gt;🧠 Why it matters&lt;/p&gt;

&lt;p&gt;ngxsmk-datatable now goes beyond tables — it’s a data platform for building dashboards, internal tools, and enterprise UIs faster than ever.&lt;/p&gt;

&lt;p&gt;🔗 Check out the full release:&lt;br&gt;
👉 &lt;a href="https://github.com/toozuuu/ngxsmk-datatable/releases/tag/1.7.0" rel="noopener noreferrer"&gt;https://github.com/toozuuu/ngxsmk-datatable/releases/tag/1.7.0&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Angular #WebDev #OpenSource #DataTable #Frontend #EnterpriseUI
&lt;/h1&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>angular</category>
      <category>javascript</category>
    </item>
    <item>
      <title>ngxsmk-datatable v1.1.0 – Type-Safe Angular Tables with Virtual Scrolling &amp; Frozen Columns</title>
      <dc:creator>Sachin Dilshan</dc:creator>
      <pubDate>Tue, 28 Oct 2025 21:45:57 +0000</pubDate>
      <link>https://forem.com/toozuuu/ngxsmk-datatable-v110-type-safe-angular-tables-with-virtual-scrolling-frozen-columns-9k5</link>
      <guid>https://forem.com/toozuuu/ngxsmk-datatable-v110-type-safe-angular-tables-with-virtual-scrolling-frozen-columns-9k5</guid>
      <description>&lt;p&gt;Hey Angular devs! 👋&lt;/p&gt;

&lt;p&gt;The ngxsmk-datatable library just released v1.1.0, and it comes with some great updates:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Full TypeScript type safety for rows, columns, and templates – no more  runtime surprises!&lt;/li&gt;
&lt;li&gt;Virtual scrolling for smooth performance with large datasets.&lt;/li&gt;
&lt;li&gt;Frozen columns for better usability in wide tables.&lt;/li&gt;
&lt;li&gt;Improved row selection and checkbox handling.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It’s perfect if you work with large data tables in Angular and want both performance and safety.&lt;/p&gt;

&lt;p&gt;Check it out here: &lt;a href="https://github.com/toozuuu/ngxsmk-datatable" rel="noopener noreferrer"&gt;GitHub – ngxsmk-datatable&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Would love to hear how others plan to use it in their projects!&lt;/p&gt;

</description>
      <category>angular</category>
      <category>webdev</category>
      <category>frontend</category>
      <category>spanish</category>
    </item>
    <item>
      <title>Stop the Bloat: Introducing lite-schema-check, the Zero-Dependency Runtime Validator You Didn't Know You Needed</title>
      <dc:creator>Sachin Dilshan</dc:creator>
      <pubDate>Sun, 26 Oct 2025 22:43:28 +0000</pubDate>
      <link>https://forem.com/toozuuu/stop-the-bloat-introducing-lite-schema-check-the-zero-dependency-runtime-validator-you-didnt-2j73</link>
      <guid>https://forem.com/toozuuu/stop-the-bloat-introducing-lite-schema-check-the-zero-dependency-runtime-validator-you-didnt-2j73</guid>
      <description>&lt;p&gt;Hello DEV Community!&lt;/p&gt;

&lt;p&gt;I've just released a minimal, zero-dependency NPM package called lite-schema-check and I think it directly addresses a common pattern in the JavaScript ecosystem.&lt;/p&gt;

&lt;p&gt;We all know the moment: we need to check if a simple object—a configuration file, an options parameter, or a JSON payload—has the right keys and types. The common choices are either writing verbose, custom type checks or pulling in a huge dependency like Zod or Joi.&lt;/p&gt;

&lt;p&gt;lite-schema-check is the ultimate minimalist solution, built for Node.js microservices and lightweight libraries where every kilobyte counts.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What is it and Why is it "Lite"?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This utility exports a single, pure function: validate(object, schema).&lt;/p&gt;

&lt;p&gt;It performs the minimum viable validation: it only checks for key presence and primitive type matching. It validates for string, number, boolean, array, and object.&lt;/p&gt;

&lt;p&gt;The core philosophy is minimalism over complex data modeling. It doesn't do nested validation, unions, or transforms—that's what the bigger libraries are for. It exists to solve the 80% case: ensuring a flat config object or API input meets its basic primitive contract. And crucially, it does this with zero external dependencies.&lt;/p&gt;

&lt;p&gt;🎯 Use Case: Fail Fast on External Data&lt;br&gt;
This tool is perfect for asserting data integrity when dealing with inputs that TypeScript can't guarantee at compile time (like API responses or environment variables).&lt;/p&gt;

&lt;p&gt;Imagine validating a module's configuration object:&lt;/p&gt;

&lt;p&gt;TypeScript&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Define the expected contract
const MODULE_CONFIG_SCHEMA = {
  apiKey: 'string',
  port: 'number',
  useCache: 'boolean',
};

// Check the incoming data
const options = getExternalConfig(); 

const result = validate(options, MODULE_CONFIG_SCHEMA);

if (!result.isValid) {
    // Throw a clear, immediate error on initialization
    throw new Error(`Config validation failed: ${result.errors[0].message}`);
}
// Configuration is now safe and guaranteed to have the right primitives.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If a user passes the wrong type (e.g., port: "8080"), the app fails immediately with a clear error message, saving hours of downstream debugging.&lt;/p&gt;

&lt;p&gt;🛠️ Get Involved&lt;br&gt;
This is a true MVP. I'd love your feedback, especially on:&lt;/p&gt;

&lt;p&gt;The "Lite" Promise: What is the next most critical, simple feature that could be added without breaking the zero-dependency promise?&lt;/p&gt;

&lt;p&gt;Missing Primitives: Should we add types like 'function' or 'symbol'?&lt;/p&gt;

&lt;p&gt;Check out the GitHub repo and help us keep the utility ultra-light!&lt;/p&gt;

&lt;p&gt;➡️ GitHub Repo: &lt;a href="https://github.com/toozuuu/lite-schema-check" rel="noopener noreferrer"&gt;https://github.com/toozuuu/lite-schema-check&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  javascript #typescript #nodejs #opensource #validation
&lt;/h1&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>node</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Angular Datepicker v1.3.6: Popovers, Smooth Transitions, and a Pluggable Holiday System! 🎁</title>
      <dc:creator>Sachin Dilshan</dc:creator>
      <pubDate>Fri, 17 Oct 2025 06:25:13 +0000</pubDate>
      <link>https://forem.com/toozuuu/angular-datepicker-v110-popovers-smooth-transitions-and-a-pluggable-holiday-system-4dj9</link>
      <guid>https://forem.com/toozuuu/angular-datepicker-v110-popovers-smooth-transitions-and-a-pluggable-holiday-system-4dj9</guid>
      <description>&lt;p&gt;We've just rolled out a major feature upgrade for our Angular datepicker component, ngxsmk-datepicker, focusing heavily on delivering a cleaner user experience and powerful new extensibility points.&lt;/p&gt;

&lt;p&gt;If you're building a business application, booking system, or any tool that needs advanced date handling, this update is for you.&lt;/p&gt;

&lt;p&gt;✨ Highlights of v1.3.6&lt;br&gt;
We addressed three key areas in this release: UX flow, visual performance, and modularity.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4jerbteb5wbjd2ipy0dx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4jerbteb5wbjd2ipy0dx.png" alt=" " width="774" height="691"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3iuccjtyrf3qg2cn46gy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3iuccjtyrf3qg2cn46gy.png" alt=" " width="686" height="763"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9hofxn472pry83s0256g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9hofxn472pry83s0256g.png" alt=" " width="741" height="720"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Adaptive Display Modes (Popover &amp;amp; Inline)
We've transformed how the calendar is displayed, making it flexible for any screen or layout:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Popover Mode (New Default): The calendar appears as a discrete popover when the input field is clicked. This mode is excellent for forms and complex views where space is limited. It automatically includes a Clear button in both the input field and the popover footer.&lt;/p&gt;

&lt;p&gt;Inline Mode: For dashboards or permanent views, setting the [inline] input to true embeds the calendar directly into the page.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;🚀 Silky Smooth Month Navigation&lt;br&gt;
Nobody likes jumpy UI elements. We've introduced fluid CSS transitions to the month navigation. When you click the arrow buttons, the calendar grid now slides smoothly into the next month, dramatically enhancing the component’s overall feel and visual polish.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;🎁 The Big Feature: Pluggable Holiday Provider&lt;br&gt;
This is the largest architectural improvement. For any application dealing with specific dates (like scheduling, payroll, or booking), marking and disabling non-working days is crucial.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We introduced the HolidayProvider interface, allowing you to inject your own logic for defining important dates.&lt;/p&gt;

&lt;p&gt;How it works:&lt;/p&gt;

&lt;p&gt;You create a simple class that implements the new interface, fetching or defining your custom rules (e.g., regional holidays, company shutdown days).&lt;/p&gt;

&lt;p&gt;TypeScript&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export interface HolidayProvider {
  isHoliday(date: Date): boolean;
  getHolidayLabel?(date: Date): string | null;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The datepicker uses your provider to automatically style (mark) these dates and display a tooltip with the holiday name.&lt;/p&gt;

&lt;p&gt;Use the new [disableHolidays] input to instantly enforce these rules by blocking selection on all provided dates. This simplifies validation logic significantly!&lt;/p&gt;

&lt;p&gt;Source Code&lt;/p&gt;

&lt;p&gt;Want to see the fluid transitions or test the holiday disabling toggle?&lt;/p&gt;

&lt;p&gt;Source Code: &lt;a href="https://github.com/toozuuu/ngxsmk-datepicker" rel="noopener noreferrer"&gt;https://github.com/toozuuu/ngxsmk-datepicker&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;NPM: &lt;a href="https://www.npmjs.com/package/ngxsmk-datepicker" rel="noopener noreferrer"&gt;https://www.npmjs.com/package/ngxsmk-datepicker&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Feel free to check out the repo, submit issues, or ask any questions about integrating the new features! We look forward to your feedback.&lt;/p&gt;

</description>
      <category>angular</category>
      <category>typescript</category>
      <category>webdev</category>
      <category>frontend</category>
    </item>
    <item>
      <title>I built this to simplify date range selection in Angular 17+.
If you’re an Angular dev, try it out and let me know what features you’d love next!
Star it on GitHub if you’d like to support the project ❤️
🔗 https://github.com/toozuuu/ngxsmk-datepicker</title>
      <dc:creator>Sachin Dilshan</dc:creator>
      <pubDate>Tue, 14 Oct 2025 20:12:04 +0000</pubDate>
      <link>https://forem.com/toozuuu/i-built-this-to-simplify-date-range-selection-in-angular-17-if-youre-an-angular-dev-try-it-out-4c26</link>
      <guid>https://forem.com/toozuuu/i-built-this-to-simplify-date-range-selection-in-angular-17-if-youre-an-angular-dev-try-it-out-4c26</guid>
      <description>&lt;p&gt;

&lt;/p&gt;
&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/angularfirebase/angular-20-de-la-programacion-imperativa-a-la-creacion-declarativa-de-componentes-dinamicos-42e" class="crayons-story__hidden-navigation-link"&gt;Angular 20: De la programación imperativa a la creación declarativa de componentes dinámicos&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;
          &lt;a class="crayons-logo crayons-logo--l" href="/angularfirebase"&gt;
            &lt;img alt="Angular Firebase logo" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F821%2Fd43c326b-2812-4d5d-a7e0-f13d3a9567d7.png" class="crayons-logo__image"&gt;
          &lt;/a&gt;

          &lt;a href="/antoniocardenas" class="crayons-avatar  crayons-avatar--s absolute -right-2 -bottom-2 border-solid border-2 border-base-inverted  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F175287%2F355839ae-97e4-4466-8e8e-53a4b48782f4.jpg" alt="antoniocardenas profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/antoniocardenas" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Antonio Cardenas 
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Antonio Cardenas 
                
              
              &lt;div id="story-author-preview-content-2901912" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/antoniocardenas" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F175287%2F355839ae-97e4-4466-8e8e-53a4b48782f4.jpg" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Antonio Cardenas &lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

            &lt;span&gt;
              &lt;span class="crayons-story__tertiary fw-normal"&gt; for &lt;/span&gt;&lt;a href="/angularfirebase" class="crayons-story__secondary fw-medium"&gt;Angular Firebase&lt;/a&gt;
            &lt;/span&gt;
          &lt;/div&gt;
          &lt;a href="https://dev.to/angularfirebase/angular-20-de-la-programacion-imperativa-a-la-creacion-declarativa-de-componentes-dinamicos-42e" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Oct 9 '25&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/angularfirebase/angular-20-de-la-programacion-imperativa-a-la-creacion-declarativa-de-componentes-dinamicos-42e" id="article-link-2901912"&gt;
          Angular 20: De la programación imperativa a la creación declarativa de componentes dinámicos
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/angular"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;angular&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/webdev"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;webdev&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/spanish"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;spanish&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/frontend"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;frontend&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/angularfirebase/angular-20-de-la-programacion-imperativa-a-la-creacion-declarativa-de-componentes-dinamicos-42e" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/exploding-head-daceb38d627e6ae9b730f36a1e390fca556a4289d5a41abb2c35068ad3e2c4b5.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/multi-unicorn-b44d6f8c23cdd00964192bedc38af3e82463978aa611b4365bd33a0f1f4f3e97.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;12&lt;span class="hidden s:inline"&gt; reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/angularfirebase/angular-20-de-la-programacion-imperativa-a-la-creacion-declarativa-de-componentes-dinamicos-42e#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


              &lt;span class="hidden s:inline"&gt;Add Comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            6 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;




&lt;p&gt;

&lt;/p&gt;
&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
        &lt;div class="c-embed__cover"&gt;
          &lt;a href="https://github.com/toozuuu/ngxsmk-datepicker" class="c-link align-middle" rel="noopener noreferrer"&gt;
            &lt;img alt="" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fopengraph.githubassets.com%2F70b7f6df73267b52267ea5d95ee8857ffc565ad30949f589443b3a7acce86e7c%2Ftoozuuu%2Fngxsmk-datepicker" height="auto" class="m-0"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="c-embed__body"&gt;
        &lt;h2 class="fs-xl lh-tight"&gt;
          &lt;a href="https://github.com/toozuuu/ngxsmk-datepicker" rel="noopener noreferrer" class="c-link"&gt;
            GitHub - toozuuu/ngxsmk-datepicker: A powerful, modern, and highly customizable Angular date range picker with built-in time selection. · GitHub
          &lt;/a&gt;
        &lt;/h2&gt;
          &lt;p class="truncate-at-3"&gt;
            A powerful, modern, and highly customizable Angular date range picker with built-in time selection. - toozuuu/ngxsmk-datepicker
          &lt;/p&gt;
        &lt;div class="color-secondary fs-s flex items-center"&gt;
            &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.githubassets.com%2Ffavicons%2Ffavicon.svg"&gt;
          github.com
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;




</description>
      <category>angular</category>
      <category>webdev</category>
      <category>spanish</category>
      <category>frontend</category>
    </item>
    <item>
      <title>I built a zero-dependency, standalone date range picker for Angular 17+ (ngxsmk-datepicker)</title>
      <dc:creator>Sachin Dilshan</dc:creator>
      <pubDate>Thu, 09 Oct 2025 10:12:46 +0000</pubDate>
      <link>https://forem.com/toozuuu/i-built-a-zero-dependency-standalone-date-range-picker-for-angular-17-ngxsmk-datepicker-4g7d</link>
      <guid>https://forem.com/toozuuu/i-built-a-zero-dependency-standalone-date-range-picker-for-angular-17-ngxsmk-datepicker-4g7d</guid>
      <description>&lt;p&gt;Hello Angular devs!&lt;/p&gt;

&lt;p&gt;I've been working on a new component and am excited to share ngxsmk-datepicker 📅. This is a highly customizable date range picker built from the ground up to be a zero-dependency, standalone component for the latest versions of Angular (17+).&lt;/p&gt;

&lt;p&gt;The goal was to create a feature-rich datepicker that doesn't force users to pull in a massive UI library.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7ld498iv1ayav6ve27uh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7ld498iv1ayav6ve27uh.png" alt=" " width="679" height="590"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frnyehe39oxqw5kb47plm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frnyehe39oxqw5kb47plm.png" alt=" " width="674" height="541"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs6a2xyol5o5xaj7dtva2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs6a2xyol5o5xaj7dtva2.png" alt=" " width="676" height="554"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Why use ngxsmk-datepicker?&lt;br&gt;
⚡ Truly Standalone: No external dependencies. Just drop the component in for maximum performance and smallest bundle size.&lt;/p&gt;

&lt;p&gt;🌍 Advanced i18n &amp;amp; Localization: It automatically handles the complex regional settings, correctly formatting month names and determining the first day of the week based on the user's browser locale (navigator.language).&lt;/p&gt;

&lt;p&gt;🎨 Highly Customizable: Built-in Light/Dark themes and easy custom color theming using simple CSS variables.&lt;/p&gt;

&lt;p&gt;🛠️ Full Flexibility: Supports Single Date and Date Range modes, comes with pre-defined quick ranges (like "Last 7 Days"), and allows for custom date disabling logic (e.g., locking out weekends/holidays).&lt;/p&gt;

&lt;p&gt;🔄 Input Compatibility: Accepts Date objects, strings, Moment, or Dayjs objects for maximum compatibility.&lt;/p&gt;

&lt;p&gt;I'm currently working on version 1.0.4 and would love any feedback from the community on features or styling, especially regarding real-world use cases!&lt;/p&gt;

&lt;p&gt;GitHub / Installation:&lt;a href="https://github.com/toozuuu/ngxsmk-datepicker" rel="noopener noreferrer"&gt;https://github.com/toozuuu/ngxsmk-datepicker&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;NPM: &lt;a href="https://www.npmjs.com/package/ngxsmk-datepicker" rel="noopener noreferrer"&gt;https://www.npmjs.com/package/ngxsmk-datepicker&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thanks for checking it out!&lt;/p&gt;

</description>
      <category>angular</category>
      <category>webdev</category>
      <category>frontend</category>
      <category>spanish</category>
    </item>
    <item>
      <title>🚀 Introducing ngxsmk-stripe: A Modern Angular Stripe Plugin</title>
      <dc:creator>Sachin Dilshan</dc:creator>
      <pubDate>Wed, 20 Aug 2025 04:58:02 +0000</pubDate>
      <link>https://forem.com/toozuuu/introducing-ngxsmk-stripe-a-modern-angular-stripe-plugin-2klp</link>
      <guid>https://forem.com/toozuuu/introducing-ngxsmk-stripe-a-modern-angular-stripe-plugin-2klp</guid>
      <description>&lt;p&gt;I’m excited to share my latest open-source project: &lt;strong&gt;ngxsmk-stripe&lt;/strong&gt;, an Angular 17+ plugin that makes integrating Stripe payments simple, customizable, and future-proof.&lt;/p&gt;




&lt;h2&gt;
  
  
  💳 Why I Built This
&lt;/h2&gt;

&lt;p&gt;If you’ve ever tried to integrate Stripe into an Angular app, you know it can feel a bit overwhelming. I wanted a solution that was:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ &lt;strong&gt;Angular-first&lt;/strong&gt; (built with standalone components)&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Future-proof&lt;/strong&gt; (compatible with Angular 17+)&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Flexible&lt;/strong&gt; (one-time payments + subscriptions)&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Customizable&lt;/strong&gt; (SCSS theming + Stripe Appearance API)&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Developer-friendly&lt;/strong&gt; (success/error event emitters)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That’s how &lt;strong&gt;ngxsmk-stripe&lt;/strong&gt; was born!&lt;/p&gt;




&lt;h2&gt;
  
  
  🔑 Key Features
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;💳 One-time payments via Stripe PaymentElement&lt;/li&gt;
&lt;li&gt;🔄 Subscription &amp;amp; recurring billing with SetupIntent&lt;/li&gt;
&lt;li&gt;🎨 Theme customization using SCSS + Stripe Appearance API&lt;/li&gt;
&lt;li&gt;🌍 Localization support (&lt;code&gt;locale&lt;/code&gt; input)&lt;/li&gt;
&lt;li&gt;⚡ Standalone Angular components (no NgModule required)&lt;/li&gt;
&lt;li&gt;📤 Event emitters for handling success and error states&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  ⚡ Quick Example
&lt;/h2&gt;

&lt;p&gt;Here’s how easy it is to drop a payment form into your Angular app:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;ngxsmk-stripe-payment&lt;/span&gt;
  &lt;span class="na"&gt;[publicKey]=&lt;/span&gt;&lt;span class="s"&gt;"publicKey"&lt;/span&gt;
  &lt;span class="na"&gt;[clientSecret]=&lt;/span&gt;&lt;span class="s"&gt;"paymentClientSecret"&lt;/span&gt;
  &lt;span class="na"&gt;[returnUrl]=&lt;/span&gt;&lt;span class="s"&gt;"returnUrl"&lt;/span&gt;
  &lt;span class="na"&gt;[appearance]=&lt;/span&gt;&lt;span class="s"&gt;"appearance"&lt;/span&gt;
  &lt;span class="na"&gt;(paymentSuccess)=&lt;/span&gt;&lt;span class="s"&gt;"onPaymentSuccess($event)"&lt;/span&gt;
  &lt;span class="na"&gt;(paymentError)=&lt;/span&gt;&lt;span class="s"&gt;"onPaymentError($event)"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/ngxsmk-stripe-payment&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And for subscriptions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;ngxsmk-stripe-subscription&lt;/span&gt;
  &lt;span class="na"&gt;[publicKey]=&lt;/span&gt;&lt;span class="s"&gt;"publicKey"&lt;/span&gt;
  &lt;span class="na"&gt;[clientSecret]=&lt;/span&gt;&lt;span class="s"&gt;"subscriptionClientSecret"&lt;/span&gt;
  &lt;span class="na"&gt;[returnUrl]=&lt;/span&gt;&lt;span class="s"&gt;"returnUrl"&lt;/span&gt;
  &lt;span class="na"&gt;[appearance]=&lt;/span&gt;&lt;span class="s"&gt;"appearance"&lt;/span&gt;
  &lt;span class="na"&gt;(subscriptionSuccess)=&lt;/span&gt;&lt;span class="s"&gt;"onSubSuccess($event)"&lt;/span&gt;
  &lt;span class="na"&gt;(subscriptionError)=&lt;/span&gt;&lt;span class="s"&gt;"onSubError($event)"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/ngxsmk-stripe-subscription&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🎨 Customization
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Use &lt;strong&gt;SCSS variables&lt;/strong&gt; for button styles, colors, and typography&lt;/li&gt;
&lt;li&gt;Leverage Stripe’s &lt;strong&gt;Appearance API&lt;/strong&gt; for advanced UI theming&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  📦 Installation
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;ngxsmk-stripe @stripe/stripe-js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🛠 Contributing
&lt;/h2&gt;

&lt;p&gt;I’d love to see the community extend this plugin with new features (like saved payment methods, invoicing tools, etc.). PRs are welcome!&lt;/p&gt;

&lt;p&gt;Repo 👉 &lt;a href="https://github.com/toozuuu/ngxsmk-stripe" rel="noopener noreferrer"&gt;GitHub: ngxsmk-stripe&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  📜 Closing Thoughts
&lt;/h2&gt;

&lt;p&gt;With &lt;strong&gt;ngxsmk-stripe&lt;/strong&gt;, you can focus on building your product while handling payments securely and elegantly in Angular. I hope this saves other devs the hours I spent piecing everything together!&lt;/p&gt;

&lt;p&gt;🚀 Try it out, give it a ⭐ on GitHub, and let me know your feedback!&lt;/p&gt;

</description>
      <category>angular</category>
      <category>stripe</category>
      <category>opensource</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Drop-in spinner for any Angular 17+ button (no CSS imports): ngxsmk-button-spinner</title>
      <dc:creator>Sachin Dilshan</dc:creator>
      <pubDate>Wed, 20 Aug 2025 04:45:07 +0000</pubDate>
      <link>https://forem.com/toozuuu/drop-in-spinner-for-any-angular-17-button-no-css-imports-ngxsmk-button-spinner-3ad6</link>
      <guid>https://forem.com/toozuuu/drop-in-spinner-for-any-angular-17-button-no-css-imports-ngxsmk-button-spinner-3ad6</guid>
      <description>&lt;h1&gt;
  
  
  Drop-in spinner for any Angular 17+ button (no CSS imports): &lt;code&gt;ngxsmk-button-spinner&lt;/code&gt;
&lt;/h1&gt;

&lt;blockquote&gt;
&lt;p&gt;Add a &lt;strong&gt;loading spinner&lt;/strong&gt; to any existing &lt;code&gt;&amp;lt;button&amp;gt;&lt;/code&gt; with one attribute.&lt;br&gt;
No component swap. &lt;strong&gt;No global stylesheet&lt;/strong&gt;. SSR-safe. A11y-friendly.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyy1wpsf53hmsp50v13jp.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyy1wpsf53hmsp50v13jp.gif" alt=" " width="380" height="266"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  ✨ What it is
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;ngxsmk-button-spinner&lt;/code&gt; is a tiny &lt;strong&gt;Angular 17+ directive&lt;/strong&gt; that overlays a spinner on your button during async work.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ &lt;strong&gt;Drop-in&lt;/strong&gt;: &lt;code&gt;[ngxsmkButtonSpinner]="loading"&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;✅ &lt;strong&gt;Two modes&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Inline&lt;/strong&gt; (default): spinner appears after the text with a small gap&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Overlay&lt;/strong&gt; (centered): &lt;code&gt;[ngxsmkButtonSpinnerHideLabel]="true"&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;&lt;p&gt;✅ &lt;strong&gt;Zero CSS imports&lt;/strong&gt; — styles are injected once&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;✅ &lt;strong&gt;CSS variables&lt;/strong&gt; theming (bind directly in the template)&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;✅ &lt;strong&gt;A11y&lt;/strong&gt;: &lt;code&gt;role="status"&lt;/code&gt;, configurable &lt;code&gt;aria-label&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;✅ &lt;strong&gt;SSR-safe&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;

&lt;/ul&gt;




&lt;h2&gt;
  
  
  🧩 Install
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm i ngxsmk-button-spinner
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Peer deps: &lt;code&gt;@angular/core@&amp;gt;=17&lt;/code&gt;, &lt;code&gt;@angular/common@&amp;gt;=17&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  🚀 Quick start (Signals)
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// app.component.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;signal&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;NgxSmkButtonSpinnerDirective&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ngxsmk-button-spinner&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;app-root&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;standalone&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;imports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;NgxSmkButtonSpinnerDirective&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`
    &amp;lt;button [ngxsmkButtonSpinner]="saving()" (click)="save()"&amp;gt;
      Save
    &amp;lt;/button&amp;gt;
  `&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AppComponent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;saving&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;saving&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;saving&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;1200&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That’s it. No module boilerplate. No style imports.&lt;/p&gt;




&lt;h2&gt;
  
  
  🎛️ Theming (recommended): bind CSS variables directly
&lt;/h2&gt;

&lt;p&gt;Bind these CSS variables &lt;strong&gt;right on the button&lt;/strong&gt; for instant updates (no restarts, no object cloning):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;--ngxsmk-color&lt;/code&gt; (spinner color)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--ngxsmk-track&lt;/code&gt; (trail color, default &lt;code&gt;transparent&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--ngxsmk-thickness&lt;/code&gt; (&lt;code&gt;2px&lt;/code&gt;, &lt;code&gt;3px&lt;/code&gt;, …)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--ngxsmk-size&lt;/code&gt; (&lt;code&gt;20px&lt;/code&gt;, &lt;code&gt;1.2em&lt;/code&gt;, …)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--ngxsmk-speed&lt;/code&gt; (&lt;code&gt;700ms&lt;/code&gt;, &lt;code&gt;450ms&lt;/code&gt;, …)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Inline (default)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt;
  &lt;span class="na"&gt;[ngxsmkButtonSpinner]=&lt;/span&gt;&lt;span class="s"&gt;"loading"&lt;/span&gt;
  &lt;span class="na"&gt;[style.--ngxsmk-color]=&lt;/span&gt;&lt;span class="s"&gt;"'#0ea5e9'"&lt;/span&gt;
  &lt;span class="na"&gt;[style.--ngxsmk-thickness]=&lt;/span&gt;&lt;span class="s"&gt;"'2px'"&lt;/span&gt;
  &lt;span class="na"&gt;[style.--ngxsmk-size]=&lt;/span&gt;&lt;span class="s"&gt;"'22px'"&lt;/span&gt;
  &lt;span class="na"&gt;[style.--ngxsmk-speed]=&lt;/span&gt;&lt;span class="s"&gt;"'600ms'"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  Publish
&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Overlay (centered, text hidden)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt;
  &lt;span class="na"&gt;[ngxsmkButtonSpinner]=&lt;/span&gt;&lt;span class="s"&gt;"loading"&lt;/span&gt;
  &lt;span class="na"&gt;[ngxsmkButtonSpinnerHideLabel]=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;
  &lt;span class="na"&gt;[style.--ngxsmk-color]=&lt;/span&gt;&lt;span class="s"&gt;"'#0ea5e9'"&lt;/span&gt;
  &lt;span class="na"&gt;[style.--ngxsmk-thickness]=&lt;/span&gt;&lt;span class="s"&gt;"'6px'"&lt;/span&gt;
  &lt;span class="na"&gt;[style.--ngxsmk-size]=&lt;/span&gt;&lt;span class="s"&gt;"'20px'"&lt;/span&gt;
  &lt;span class="na"&gt;[style.--ngxsmk-speed]=&lt;/span&gt;&lt;span class="s"&gt;"'500ms'"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  Save
&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Prefer variable binding over passing a theme object — it updates immediately with Angular HMR/Signals and avoids change-detection gotchas.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You can also set per-class defaults:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="c"&gt;/* component.css */&lt;/span&gt;
&lt;span class="nc"&gt;.primary-btn&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;--ngxsmk-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#2563eb&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--ngxsmk-thickness&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--ngxsmk-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;22px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--ngxsmk-speed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;450ms&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🧠 API (tiny)
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt;
  &lt;span class="na"&gt;[ngxsmkButtonSpinner]=&lt;/span&gt;&lt;span class="s"&gt;"loading"&lt;/span&gt;         &lt;span class="err"&gt;&amp;lt;!&lt;/span&gt;&lt;span class="na"&gt;--&lt;/span&gt; &lt;span class="na"&gt;boolean&lt;/span&gt; &lt;span class="na"&gt;or&lt;/span&gt; &lt;span class="na"&gt;Signal&lt;/span&gt;&lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="na"&gt;boolean&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; --&amp;gt;
  [ngxsmkButtonSpinnerHideLabel]="true"   &lt;span class="c"&gt;&amp;lt;!-- optional overlay mode --&amp;gt;&lt;/span&gt;
  [ngxsmkButtonSpinnerOptions]="{ ariaLabel: 'Saving' }"&amp;gt;
  Save
&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;ngxsmkButtonSpinner: boolean | Signal&amp;lt;boolean)&lt;/code&gt; — toggles spinner; also disables the button.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ngxsmkButtonSpinnerHideLabel?: boolean | Signal&amp;lt;boolean)&lt;/code&gt; — overlay mode when true.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ngxsmkButtonSpinnerOptions?: { ariaLabel?: string }&lt;/code&gt; — a11y label for the spinner.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  ♿ Accessibility
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Spinner uses &lt;code&gt;role="status"&lt;/code&gt; with an &lt;code&gt;aria-label&lt;/code&gt; (default: “Loading”).&lt;/li&gt;
&lt;li&gt;Button is disabled while loading to prevent duplicate submissions.&lt;/li&gt;
&lt;li&gt;Overlay mode hides the label visually but keeps the status for screen readers.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🌐 SSR / hydration
&lt;/h2&gt;

&lt;p&gt;The directive injects DOM only in the &lt;strong&gt;browser&lt;/strong&gt; after view init. Toggle &lt;code&gt;loading&lt;/code&gt; in response to user actions or browser-only effects.&lt;/p&gt;




&lt;h2&gt;
  
  
  🛠️ Troubleshooting
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Theme not updating&lt;/strong&gt;
Bind CSS variables directly (&lt;code&gt;[style.--ngxsmk-*]&lt;/code&gt;). This updates instantly without rebuilding.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Spinner not centered in overlay&lt;/strong&gt;
Ensure the button doesn’t clip positioned children with &lt;code&gt;overflow: hidden&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Text not hiding in overlay&lt;/strong&gt;
Upgrade to the latest build — the label is wrapped and hidden safely.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  📦 Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;GitHub: &lt;a href="https://github.com/toozuuu/ngxsmk-button-spinner" rel="noopener noreferrer"&gt;https://github.com/toozuuu/ngxsmk-button-spinner&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;npm: &lt;a href="https://www.npmjs.com/package/ngxsmk-button-spinner" rel="noopener noreferrer"&gt;https://www.npmjs.com/package/ngxsmk-button-spinner&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you build something with it, drop a comment — I’d love to see it!&lt;/p&gt;

</description>
      <category>angular</category>
      <category>webdev</category>
      <category>opensource</category>
      <category>javascript</category>
    </item>
    <item>
      <title>ngxsmk-tel-input — International Phone Input for Angular (E.164, i18n, RTL)</title>
      <dc:creator>Sachin Dilshan</dc:creator>
      <pubDate>Mon, 18 Aug 2025 03:19:02 +0000</pubDate>
      <link>https://forem.com/toozuuu/introducing-ngxsmk-tel-input-international-phone-input-for-angular-17-19-1ia</link>
      <guid>https://forem.com/toozuuu/introducing-ngxsmk-tel-input-international-phone-input-for-angular-17-19-1ia</guid>
      <description>&lt;p&gt;I’ve shipped a small, focused UI component for modern Angular apps: an international telephone input with country flags, dropdown, and real validation/formatting.&lt;/p&gt;

&lt;p&gt;It wraps the excellent intl-tel-input for UI and libphonenumber-js for validation/parsing, and exposes a clean Angular API that works with Reactive &amp;amp; Template-driven Forms (CVA). It emits E.164 numbers by default (e.g. +14155550123), and is SSR-safe.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F24mr7n20mut0u0xqrxoi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F24mr7n20mut0u0xqrxoi.png" alt=" " width="465" height="170"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffiegm4h8qvmqionh0nqh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffiegm4h8qvmqionh0nqh.png" alt=" " width="450" height="172"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;TL;DR&lt;/p&gt;

&lt;p&gt;✅ UI via intl-tel-input, rules via libphonenumber-js&lt;/p&gt;

&lt;p&gt;✅ Emits clean E.164 values&lt;/p&gt;

&lt;p&gt;✅ Works with Reactive &amp;amp; Template forms (ControlValueAccessor)&lt;/p&gt;

&lt;p&gt;✅ Angular 17–19, standalone, SSR-friendly&lt;/p&gt;

&lt;p&gt;✅ Options: separateDialCode, nationalMode, preferredCountries, attach dropdown to &lt;/p&gt;, sizes, variants, clear button, autofocus, select-on-focus

&lt;p&gt;🌍 Localization &amp;amp; RTL: customize labels, country names, and direction&lt;/p&gt;

&lt;p&gt;🔒 Optional digits-only input mode (with single leading +)&lt;/p&gt;

&lt;p&gt;NPM: &lt;a href="https://www.npmjs.com/package/ngxsmk-tel-input" rel="noopener noreferrer"&gt;https://www.npmjs.com/package/ngxsmk-tel-input&lt;/a&gt;&lt;br&gt;
GitHub: &lt;a href="https://github.com/toozuuu/ngxsmk-tel-input" rel="noopener noreferrer"&gt;https://github.com/toozuuu/ngxsmk-tel-input&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Install&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm i ngxsmk-tel-input intl-tel-input libphonenumber-js&lt;br&gt;
&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Add styles &amp;amp; flag assets in your app (not the library). Update angular.json:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
{
  "projects": {
    "your-app": {
      "architect": {
        "build": {
          "options": {
            "styles": [
              "node_modules/intl-tel-input/build/css/intlTelInput.css"
            ],
            "assets": [
              { "glob": "**/*", "input": "node_modules/intl-tel-input/build/img", "output": "assets/intl-tel-input/img" }
            ]
          }
        }
      }
    }
  }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Optional (helps some setups resolve flags):&lt;/p&gt;

&lt;p&gt;/* global styles */&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.iti__flag { background-image: url("/assets/intl-tel-input/img/flags.png"); }
@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) {
  .iti__flag { background-image: url("/assets/intl-tel-input/img/flags@2x.png"); }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Restart your dev server after editing angular.json.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Quick Start (Reactive Forms)&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// app.component.ts
import { Component, inject } from '@angular/core';
import { ReactiveFormsModule, FormBuilder, Validators } from '@angular/forms';
import { JsonPipe } from '@angular/common';
import { NgxsmkTelInputComponent } from 'ngxsmk-tel-input';

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [ReactiveFormsModule, NgxsmkTelInputComponent, JsonPipe],
  template: `
    &amp;lt;form [formGroup]="fg" style="max-width:420px;display:grid;gap:12px"&amp;gt;
      &amp;lt;ngxsmk-tel-input
        formControlName="phone"
        label="Phone"
        hint="Include area code"
        [initialCountry]="'US'"
        [preferredCountries]="['US','GB','AU']"&amp;gt;
      &amp;lt;/ngxsmk-tel-input&amp;gt;

      &amp;lt;pre&amp;gt;Value: {{ fg.value | json }}&amp;lt;/pre&amp;gt;
    &amp;lt;/form&amp;gt;
  `,
})
export class AppComponent {
  private readonly fb = inject(FormBuilder);
  fg = this.fb.group({ phone: ['', Validators.required] });
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Value semantics: The control emits E.164 (e.g., +14155550123) when valid, or null when empty/invalid.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Localization &amp;amp; RTL (i18n)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Customize dropdown/search labels and country names. RTL is as easy as dir="rtl".&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { Component, inject } from '@angular/core';
import { ReactiveFormsModule, FormBuilder, Validators } from '@angular/forms';
import { NgxsmkTelInputComponent, IntlTelI18n, CountryMap } from 'ngxsmk-tel-input';

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [ReactiveFormsModule, NgxsmkTelInputComponent],
  template: `
    &amp;lt;form [formGroup]="fg" style="max-width:420px;display:grid;gap:12px"&amp;gt;
      &amp;lt;ngxsmk-tel-input
        formControlName="phone"
        label="전화번호"
        hint="지역 번호를 포함하세요"
        placeholder="전화번호 입력"
        dir="ltr"
        [initialCountry]="'KR'"
        [preferredCountries]="['KR','US','JP']"
        [i18n]="koLabels"
        [localizedCountries]="koCountries"&amp;gt;
      &amp;lt;/ngxsmk-tel-input&amp;gt;

      &amp;lt;pre&amp;gt;Value: {{ fg.value | json }}&amp;lt;/pre&amp;gt;
    &amp;lt;/form&amp;gt;
  `
})
export class AppComponent {
  private fb = inject(FormBuilder);
  fg = this.fb.group({ phone: ['', Validators.required] });

  // Korean UI labels (dropdown/search/ARIA)
  koLabels: IntlTelI18n = {
    selectedCountryAriaLabel: '선택한 국가',
    countryListAriaLabel: '국가 목록',
    searchPlaceholder: '국가 검색',
    zeroSearchResults: '결과 없음',
    noCountrySelected: '선택된 국가 없음'
  };

  // Korean country names (override what you need)
  koCountries: CountryMap = {
    KR: '대한민국',
    US: '미국',
    JP: '일본',
    CN: '중국',
    GB: '영국',
    DE: '독일',
    FR: '프랑스',
    AU: '호주',
    CA: '캐나다',
    IN: '인도'
  };
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Prefer Korean? Swap labels/countries to ko-KR equivalents and set dir="ltr".&lt;/p&gt;

&lt;p&gt;Optional: Digits-Only Input&lt;/p&gt;

&lt;p&gt;You can forbid non-numeric characters (optionally allowing a single leading +):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;ngxsmk-tel-input
  formControlName="phone"
  [digitsOnly]="true"
  [allowLeadingPlus]="true"&amp;gt;
&amp;lt;/ngxsmk-tel-input&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This filters typing/paste (and keeps programmatic updates clean), while validation still uses libphonenumber-js.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Theming (CSS Variables)&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;ngxsmk-tel-input style="
  --tel-border:#cbd5e1;
  --tel-ring:#22c55e;
  --tel-radius:14px;
  --tel-dd-item-hover: rgba(34,197,94,.12);
"&amp;gt;&amp;lt;/ngxsmk-tel-input&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Dark mode? Wrap a parent in .dark — tokens adapt automatically.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;SSR Notes&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The component lazy-loads intl-tel-input only in the browser (guarded with isPlatformBrowser), so no window access on the server.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Troubleshooting&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Unstyled dropdown / missing flags → ensure CSS &amp;amp; assets are added in angular.json, then restart dev server.&lt;/li&gt;
&lt;li&gt;Flags don’t show → add the CSS override block shown above to point to /assets/intl-tel-input/img.&lt;/li&gt;
&lt;li&gt;Peer dependency conflict → the library peers target @angular/* &amp;gt;=17 &amp;lt;20.&lt;/li&gt;
&lt;li&gt;Can’t import the package in a workspace → build the lib (ng build ngxsmk-tel-input) or use a tarball install.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Roadmap &amp;amp; Contributions&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Accessibility polish &amp;amp; docs samples&lt;/li&gt;
&lt;li&gt;More presets &amp;amp; examples (StackBlitz)&lt;/li&gt;
&lt;li&gt;Community requests!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;PRs, issues, and ideas are super welcome 🙌&lt;/p&gt;

&lt;p&gt;NPM: &lt;a href="https://www.npmjs.com/package/ngxsmk-tel-input" rel="noopener noreferrer"&gt;https://www.npmjs.com/package/ngxsmk-tel-input&lt;/a&gt;&lt;br&gt;
GitHub: &lt;a href="https://github.com/toozuuu/ngxsmk-tel-input" rel="noopener noreferrer"&gt;https://github.com/toozuuu/ngxsmk-tel-input&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you try it, I’d love your feedback. Happy building! 💚&lt;/p&gt;

</description>
      <category>angular</category>
      <category>webdev</category>
      <category>npm</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
