Skip to main content

defineComponent Plugin

The defineComponent plugin is Coralite's core built-in plugin that enables dynamic template functionality. It makes available computed tokens, slots, and script execution for the template that need data processing and client-side interactivity.

When to Use defineComponent #

Use defineComponent When: #

Do NOT Use defineComponent When: #

Template Type Comparison #

Static Template (No defineComponent) #

HTML
Code copied!
<template id="simple-component">
  <div>
    <h1>{{ title }}</h1>
    <p>{{ description }}</p>
  </div>
</template>

No script tag needed - Coralite processes token replacements automatically.

Dynamic Template (With defineComponent) #

HTML
Code copied!
<template id="dynamic-component">
  <div>
    <h1>{{ greeting }}</h1>
    <button type="button" ref="actionBtn">Click me</button>
  </div>
</template>

<script type="module">  
  import { defineComponent } from 'coralite'
  
  export default defineComponent({
    tokens: {
      greeting: ({ name }) => `Hello, ${name}!`
    },
    client: {
      script: ({ values, helpers }) => {
        const btn = helpers.refs('actionBtn')
        btn.addEventListener('click', () => {
          console.log('Button clicked!')
        })
      }
    }
  })
</script>

Requires defineComponent as the default export.

Basic Usage #

Here's the minimal setup for a dynamic template:

HTML
Code copied!
<template id="my-component">
  <div>
    <h1>{{ title }}</h1>
  </div>
</template>

<script type="module">  
  import { defineComponent } from 'coralite'
  
  export default defineComponent({
    tokens: {
      title: () => 'My Component Title'
    }
  })
</script>

Tokens #

Tokens are computed values that are processed at build time. They can be strings or functions that return values based on the template's context.

Token Structure #

HTML
Code copied!
<script type="module">  
  export default defineComponent({
    tokens: {
      // Static token (string)
      staticValue: 'Hello World',
  
      // Computed token (function)
      fullName: ({ firstName, lastName }) => `${firstName} ${lastName}`,
  
      // Token with data processing
      formattedDate: ({ date }) => new Date(date).toLocaleDateString(),
  
      // Token with conditional logic
      status: ({ isActive }) => isActive ? 'Active' : 'Inactive'
    }
  })
</script>

Token Context #

Token functions receive a values parameter containing:

HTML
Code copied!



<head>
  <meta name="firstName" content="Alice"></meta>
  <meta name="lastName" content="Smith"></meta>
  <title>User Profile</title>
</head>

<body>
  <user-profile age="25"></user-profile>
</body>
HTML
Code copied!
<script type="module">  
  // In defineComponent:
  export default defineComponent({
    tokens: {
      /**
       * values = {
       *  // Current page filepath
       *  $urlPathname: urlPathname,
       *  $urlDirname: pathToFileURL(dirname(urlPathname)).pathname,
       *  $filePathname: data.path.pathname,
       *  $fileDirname: data.path.dirname,
       *  $filename: data.path.filename,
       *  
       *  // Data from page meta tags
       *  meta_firstName: "Alice",
       *  meta_lastName: "Smith",
       *  meta_title: "User Profile",
       *  
       *  // Data from attribute values
       *  age: "25"
       * }
       */
      fullName: ({ meta_firstName, meta_lastName }) => `${meta_firstName} ${meta_lastName}`,
      greeting: ({ age }) => `You are ${age} years old`
    }
  })
</script>

Slots #

Slots allow you to process and transform content that is passed between custom element tags.

Basic Slot Processing #

HTML
Code copied!
<template id="card-component">
  <div class="card">
    <div class="card-content">
              {{ content }}
            </div>
  </div>
</template>

<script type="module">  
  import { defineComponent } from 'coralite'
  
  export default defineComponent({
    slots: {
      content: (slotNodes, values) => {
        // Transform slot content
        return slotNodes
      }
    }
  })
</script>

Slot Function Parameters #

Slot Example #

HTML
Code copied!


<card-component>
  <h2>Card Title</h2>
  <p>Card content goes here</p>
</card-component>
HTML
Code copied!
<script type="module">  
  // In defineComponent:
  export default defineComponent({
    slots: {
      content: (slotNodes, values) => {
        // Add classes or transform content
        return slotNodes.map(node => {
          if (node.type === 'tag' && node.name === 'h2') {
            node.attributes.class = 'card-title'
          }
          return node
        })
      }
    }
  })
</script>
<coralite-code-html>
</coralite-code-html>

Setup #

The setup function allows you to perform asynchronous initialization and data fetching before the component is rendered. It replaces the need for Top-Level Await (TLA) in component modules.

Setup Function Signature #

HTML
Code copied!
<script type="module">  
  export default defineComponent({
    client: {
      setup: async (values) => {
        // Initial data fetching or processing
        // const response = await fetch('https://api.example.com/data');
        // const data = await response.json();
  
        // Return values to be merged into the component's token values
        return {
          // fetchedData: data
          message: 'Hello from setup!'
        };
      }
    }
  })
</script>

Usage #

The object returned by setup is merged into the component's available values, making them accessible to tokens, slots, and scripts.

Script #

The script function provides client-side JavaScript execution. It gets serialized and runs in the browser after the page loads.

Script Function Signature #

HTML
Code copied!
<script type="module">  
  export default defineComponent({
    client: {
      script: ({ values, helpers }) => {
        // values: Contains processed token values
        // helpers: Contains client-side helpers like refs
  
        const btn = helpers.refs('actionBtn');
  
        btn.addEventListener('click', () => {
          console.log('Clicked!');
        });
      }
    }
  })
</script>

Script Context #

Script Helpers #

Script Example #

HTML
Code copied!
<template id="counter">
  <div>
    <h2>Count: {{ count }}</h2>
    <button type="button" ref="increment">+</button>
    <button type="button" ref="decrement">-</button>
  </div>
</template>

<script type="module">  
  import { defineComponent } from 'coralite'
  
  export default defineComponent({
    tokens: {
      count: ({ initial }) => parseInt(initial) || 0
    },
    client: {
      script: ({ values, helpers }) => {
        const refs = helpers.refs
        const increment = refs('increment')
        const decrement = refs('decrement')
  
        let count = values.count
  
        increment.addEventListener('click', () => {
          count++
          document.querySelector('h2').textContent = `Count: ${count}`
        })
  
        decrement.addEventListener('click', () => {
          count--
          document.querySelector('h2').textContent = `Count: ${count}`
        })
      }
    }
  })
</script>

Complete Example #

Here's a complete example showing all defineComponent features working together:

HTML
Code copied!



<head>
  <meta name="name" content="Coralite Pro"></meta>
  <meta name="price" content="99.99"></meta>
  <meta name="inStock" content="true"></meta>
  <title>Product Details</title>
</head>

<body>
  <product-card discount="10" show-details="true"></product-card>
</body>
HTML
Code copied!


<template id="product-card">
  <div class="product-card">
    

    <h2>{{ productName }}</h2>
    <p class="price">{{ displayPrice }}</p>
    <div class="status">{{ stockStatus }}</div>
    <div class="details">
              {{ details }}
            </div>
    <button type="button" ref="buyBtn">Buy Now</button>
  </div>
</template>

<script type="module">  
  import { defineComponent } from 'coralite'
  
  export default defineComponent({
    tokens: {
      // Computed token from page metadata
      productName: ({ $name }) => $name,
  
      // Computed token with calculation
      displayPrice: ({ $price, discount }) => {
        const price = parseFloat($price)
        const discountPercent = parseFloat(discount) || 0
        const finalPrice = price * (1 - discountPercent / 100)
        return `$${finalPrice.toFixed(2)}`
      },
  
      // Conditional token
      stockStatus: ({ $inStock }) =>
        $inStock === 'true' ? 'In Stock' : 'Out of Stock'
    },
  
    slots: {
      details: (slotNodes, values) => {
        // Only show details if show-details attribute is true
        if (values.showDetails !== 'true') {
          return []
        }
        return slotNodes
      }
    },
  
    client: {
      script: ({ values, helpers }) => {
        const refs = helpers.refs
        const buyBtn = refs('buyBtn')
  
        if (buyBtn) {
          buyBtn.addEventListener('click', () => {
            alert(`Thank you for purchasing ${values.productName}!`)
          })
        }
      }
    }
  })
</script>

Key Points #

Start Building with Coralite!

Use the scaffolding script to get jump started into your next project with Coralite

Copied commandline!