From alpinejs.dev

Install alpinejs

pnpm add @types/alpinejs alpinejs -D
import type { Alpine as AlpineType } from 'alpinejs'

/**
 * From https://bobbyhadz.com/blog/typescript-make-types-global
 */
declare global {
  const Alpine: AlpineType
  interface Window {
    Alpine: AlpineType
  }
}

export {}
import Alpine from 'alpinejs'

window.Alpine = Alpine

Alpine.start()

In app vite.config.ts.

export default defineConfig({
  // ...
  optimizeDeps: {
    include: ['alpinejs'],
  },
})

Modules

mkdir resources/front/ts/modules

AlpineJS store example

touch resources/front/ts/store-example.ts

Add to app.ts

// ...

window.Alpine = Alpine

Alpine.store('shop', {
  name: 'Alpine-Shop',
  products: ['Swiss Alp Chocolate', 'Car Alpine A110'],
})

Alpine.start()

In any Blade file.

<div x-data>
  <div x-text="$store.shop.name">shop-name</div>
    <div>
      Here you can buy:
      <ul>
        <template x-for="product in $store.shop.products">
          <li x-text="product"></li>
        </template>
      </ul>
    </div>
</div>

AlpineJS data example

touch resources/front/ts/data-example.ts
let refsAlpine: {
  text: HTMLElement
}

const copy = () => ({
  copied: false,

  init() {
    // @ts-expect-error
    refsAlpine = this.$refs
  },
  async copyText() {
    this.copied = true
    let success = false
    if (refsAlpine.text.textContent)
      await navigator.clipboard.writeText(refsAlpine.text.textContent).then(() => (success = true))

    if (!success)
      console.error('Error on copy!')

    setTimeout(() => {
      this.copied = false
    }, 3500)
  },
})

export default copy

In app.ts

// ...

window.Alpine = Alpine

Alpine.data('copy', copy)

Alpine.start()

Custom module

touch resources/front/ts/custom-module.ts
export const customModule = () => {
  const customModule = 'customModule'
  console.log(customModule)
}

In app.ts

import Alpine from 'alpinejs'
import { customModule } from '~/app/ts/custom-module'

customModule()

window.Alpine = Alpine

Boiler plate modules

Color mode

touch public/color-mode.js
const colorScheme = localStorage.getItem('color-scheme')

if (colorScheme)
  document.documentElement.classList.toggle(colorScheme, true)
else {
  const system =
    window.matchMedia &&
    window.matchMedia('(prefers-color-scheme: dark)').matches
      ? 'dark'
      : 'light'
  document.documentElement.classList.toggle(system, true)
}
touch resources/front/ts/modules/color-mode.ts
type Mode = 'light' | 'dark'
interface ModeElement {
  label: string
  key: string
}

const colorMode = () => ({
  mode: 'light' as Mode,
  list: [
    {
      label: 'Light',
      key: 'light'
    }, {
      label: 'Dark',
      key: 'dark'
    }
  ] as ModeElement[],
  key: 'color-scheme',

  init() {
    this.setMode()
  },
  switchMode(mode: Mode) {
    const body = document.documentElement
    this.list.forEach((element) => {
      body.classList.remove(element.key)
    })
    body.classList.add(mode)

    localStorage.setItem(this.key, mode)
    this.setMode(mode)


  },
  setMode(mode?: Mode) {
    const currentMode = localStorage.getItem(this.key)
    if (currentMode) {
      this.mode = currentMode as Mode
    }
    if (mode === 'light') {
      this.mode = 'light'
    }
  }
})

export default colorMode
import colorMode from './modules/color-mode'

window.Alpine = Alpine

Alpine.data('colorMode', colorMode)

Alpine.start()
touch resources/views/components/color-mode.blade.php
<div x-data="colorMode">
  <ul class="w-full space-y-1">
    <template x-for="element in list">
        <button type="button"
          x-text="element.label"
          :class="[mode === element.key ? 'bg-gray-100 dark:bg-gray-800' : '',
            'block w-full rounded-md px-2 py-1 text-left hover:bg-gray-100 dark:hover:bg-gray-800'
          ]"
          @click="switchMode(element.key)"></button>
    </template>
  </ul>
</div>