Skip to content
This repository has been archived by the owner on Oct 2, 2024. It is now read-only.

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
Signed-off-by: Christoph Schmatzler <[email protected]>
  • Loading branch information
cschmatzler committed Jul 11, 2024
1 parent 98ad01f commit 2487908
Show file tree
Hide file tree
Showing 23 changed files with 941 additions and 1,116 deletions.
80 changes: 80 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
on:
push:
branches:
- main
pull_request:

jobs:
elixir:
name: Elixir (OTP ${{matrix.otp}} | Elixir ${{matrix.elixir}})
strategy:
matrix:
include:
- elixir: 1.13.4
otp: 24.3
- elixir: 1.15.4
otp: 25.3
- elixir: 1.16.3
otp: 26.2
- elixir: 1.17.2
otp: 27.0
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Set up Elixir
uses: erlef/setup-beam@v1
with:
elixir-version: ${{ matrix.elixir }}
otp-version: ${{ matrix.otp }}

- name: Install Task
uses: arduino/setup-task@v2
with:
version: 3.x
repo-token: ${{ secrets.GITHUB_TOKEN }}

- name: Restore deps and _build cache
uses: actions/cache@v4
with:
path: |
deps
_build
key: deps-elixir-${{ runner.os }}-${{ matrix.otp }}-${{ matrix.elixir }}-${{ hashFiles('**/mix.lock') }}
restore-keys: |
deps-elixir-${{ runner.os }}-${{ matrix.otp }}-${{ matrix.elixir }}
- name: Run CI script
run: task elixir-ci

node:
name: Node
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version-file: .tool-versions

- name: Install Task
uses: arduino/setup-task@v2
with:
version: 3.x
repo-token: ${{ secrets.GITHUB_TOKEN }}

- name: Restore deps and _build cache
uses: actions/cache@v4
with:
path: |
deps
_build
key: deps-node-${{ runner.os }}-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
deps-node-${{ runner.os }}-
- name: Run CI script
run: task node-ci
5 changes: 0 additions & 5 deletions .mise.toml

This file was deleted.

1 change: 1 addition & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/hooks/dist/
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ A toolkit to build beautiful, accessible components for Phoenix using Tailwind a
This project is still at version `0.1` and should not be used in production as here still is a lot of documentation going on.

- The Turboprops Hook API will most definitely change, and the amount of hooks currently available is very limited. In addition to that,
they might not be fully documented or lack options.
they might not be fully documented or lack options.
- The Turboprop Merge API is considered stable, but it lacks the ability to configure it with custom Tailwind themes and the documentation
is considered work in progress.
is considered work in progress.

## Contributing

Expand Down Expand Up @@ -57,7 +57,7 @@ This includes:
- ARIA attributes

You can either install and use them through the hex.pm dependency and some helpers we offer to add the relevant attributes to a component,
or install them directly through npm and adding the attributes yourself.
or install them directly through npm and adding the attributes yourself.

As an example, this renders a fully accessible dropdown menu:

Expand Down
24 changes: 15 additions & 9 deletions Taskfile.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,21 +13,27 @@ tasks:
- install-dependencies
cmds:
- mix format
- npx @biomejs/biome format --write .
- npx prettier --write .

check-format:
desc: Check whether the project is formatted
ci:
desc: Run the CI pipeline
deps:
- elixir-ci
- node-ci

elixir-ci:
desc: Run the CI pipeline (Elixir)
deps:
- install-dependencies
cmds:
- mix format --check-formatted
- npx @biomejs/biome format .
- mix test

lint:
desc: Lint the project
deps:
- install-npm-dependencies
cmd: npx @biomejs/biome lint .
node-ci:
desc: Run the CI pipeline (node)
cmds:
- npx prettier --check .
- npx tsc --noEmit -p .

build:
desc: Build the hooks
Expand Down
29 changes: 0 additions & 29 deletions biome.json

This file was deleted.

8 changes: 4 additions & 4 deletions hooks/accordion.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as accordion from "@zag-js/accordion";
import { normalizeProps, spreadProps, renderPart } from "./util";
import { normalizeProps, spreadProps, renderPart, getBooleanOption } from "./util";
import { Component } from "./component";
import type { ViewHook } from "phoenix_live_view";
import type { Machine } from "@zag-js/core";
Expand Down Expand Up @@ -76,9 +76,9 @@ export default {
return {
id: this.el.id,
value: [""],
disabled: this.el.dataset.disabled === "true" || this.el.dataset.disabled === "",
multiple: this.el.dataset.multiple === "true" || this.el.dataset.multiple === "",
collapsible: this.el.dataset.collapsible === "true" || this.el.dataset.collapsible === "",
disabled: getBooleanOption(this.el, "disabled"),
multiple: getBooleanOption(this.el, "multiple"),
collapsible: getBooleanOption(this.el, "collapsible"),
onValueChange: (details: accordion.ValueChangeDetails) => {
if (this.el.dataset.onValueChange) {
this.pushEvent(this.el.dataset.onValueChange, details);
Expand Down
14 changes: 3 additions & 11 deletions hooks/collapsible.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as collapsible from "@zag-js/collapsible";
import { normalizeProps, renderPart } from "./util";
import { getOption, getBooleanOption, normalizeProps, renderPart } from "./util";
import { Component } from "./component";
import type { ViewHook } from "phoenix_live_view";
import type { Machine } from "@zag-js/core";
Expand Down Expand Up @@ -41,18 +41,10 @@ export default {
},

context(): collapsible.Context {
let dir: string | undefined = this.el.dataset.dir;
const validDirs = ["ltr", "rtl"] as const;

if (dir !== undefined && !validDirs.includes(dir as any)) {
console.error(`Invalid 'dir' specified: '${dir}'. Expected 'ltr' or 'rtl'.`);
dir = undefined;
}

return {
id: this.el.id,
dir: dir as Dir,
disabled: this.el.dataset.disabled === "true" || this.el.dataset.disabled === "",
dir: getOption(this.el, "dir", ["ltr", "rtl"]) as Dir,
disabled: getBooleanOption(this.el, "disabled"),
onOpenChange: (details: collapsible.OpenChangeDetails) => {
if (this.el.dataset.onOpenChange) {
this.pushEvent(this.el.dataset.onOpenChange, details);
Expand Down
32 changes: 8 additions & 24 deletions hooks/combobox.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as combobox from "@zag-js/combobox";
import type { Collection } from "@zag-js/collection";
import { getAttributes, restoreAttributes, normalizeProps, renderPart, spreadProps } from "./util";
import { getAttributes, restoreAttributes, normalizeProps, renderPart, spreadProps, getBooleanOption, getOption } from "./util";
import { Component } from "./component";
import type { ViewHook } from "phoenix_live_view";
import type { Machine } from "@zag-js/core";
Expand Down Expand Up @@ -94,33 +94,17 @@ export default {
},

context(): combobox.Context {
let inputBehavior: string | undefined = this.el.dataset.inputBehavior;
const validInputBehaviors = ["autohighlight", "autocomplete", "none"] as const;

if (inputBehavior !== undefined && !validInputBehaviors.includes(inputBehavior as any)) {
console.error(`Invalid 'inputBehavior' specified: '${inputBehavior}'. Expected 'autohighlight', 'autocomplete' or 'none'.`);
inputBehavior = undefined;
}

let selectionBehavior: string | undefined = this.el.dataset.selectionBehavior;
const validSelectionBehaviors = ["clear", "replace", "preserve"] as const;

if (selectionBehavior !== undefined && !validSelectionBehaviors.includes(selectionBehavior as any)) {
console.error(`Invalid 'selectionBehavior' specified: '${selectionBehavior}'. Expected 'clear', 'replace' or 'preserve'.`);
selectionBehavior = undefined;
}

return {
id: this.el.id,
name: this.el.dataset.name,
collection: this.collection(),
multiple: this.el.dataset.multiple === "true" || this.el.dataset.multiple === "",
disabled: this.el.dataset.disabled === "true" || this.el.dataset.disabled === "",
readOnly: this.el.dataset.readOnly === "true" || this.el.dataset.readOnly === "",
loopFocus: this.el.dataset.loopFocus === "true" || this.el.dataset.loopFocus === "",
allowCustomValue: this.el.dataset.allowCustomValue === "true" || this.el.dataset.allowCustomValue === "",
inputBehavior: inputBehavior as InputBehavior,
selectionBehavior: selectionBehavior as SelectionBehavior,
inputBehavior: getOption(this.el, "inputBehavior", ["autohighlight", "autocomplete", "none"]) as InputBehavior,
selectionBehavior: getOption(this.el, "selectionBehavior", ["clear", "replace", "preserve"]) as SelectionBehavior,
multiple: getBooleanOption(this.el, "multiple"),
disabled: getBooleanOption(this.el, "disabled"),
readOnly: getBooleanOption(this.el, "readOnly"),
loopFocus: getBooleanOption(this.el, "loopFocus"),
allowCustomValue: getBooleanOption(this.el, "allowCustomValue"),
onOpenChange: (details: combobox.OpenChangeDetails) => {
if (this.el.dataset.onOpenChange) {
this.pushEvent(this.el.dataset.onOpenChange, details);
Expand Down
18 changes: 5 additions & 13 deletions hooks/dialog.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as dialog from "@zag-js/dialog";
import { normalizeProps, renderPart } from "./util";
import { getOption, getBooleanOption, normalizeProps, renderPart } from "./util";
import { Component } from "./component";
import type { ViewHook } from "phoenix_live_view";
import type { Machine } from "@zag-js/core";
Expand Down Expand Up @@ -41,20 +41,12 @@ export default {
},

context(): dialog.Context {
let role: string | undefined = this.el.dataset.role;
const validRoles = ["dialog", "alertdialog"] as const;

if (role !== undefined && !validRoles.includes(role as any)) {
console.error(`Invalid 'role' specified: '${role}'. Expected 'dialog' or 'alertdialog'.`);
role = undefined;
}

return {
id: this.el.id,
role: role as Role,
preventScroll: this.el.dataset.preventScroll === "true" || this.el.dataset.preventScroll === "",
closeOnInteractOutside: this.el.dataset.closeOnInteractOutside === "true" || this.el.dataset.closeOnInteractOutside === "",
closeOnEscape: this.el.dataset.closeOnEscape === "true" || this.el.dataset.closeOnEscape === "",
role: getOption(this.el, "role", ["dialog", "alertdialog"]) as Role,
preventScroll: getBooleanOption(this.el, "preventScroll"),
closeOnInteractOutside: getBooleanOption(this.el, "closeOnInteractOutside"),
closeOnEscape: getBooleanOption(this.el, "closeOnEscape"),
onOpenChange: (details: dialog.OpenChangeDetails) => {
if (this.el.dataset.onOpenChange) {
this.pushEvent(this.el.dataset.onOpenChange, details);
Expand Down
Loading

0 comments on commit 2487908

Please sign in to comment.