@phila/phila-ui-switch 0.0.1-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,93 @@
1
+ # Switch Component
2
+
3
+ City of Philadelphia switch input component with TypeScript support.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ pnpm add @phila/phila-ui-switch
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ```vue
14
+ <template>
15
+ <Switch v-model="isEnabled">Enable notifications</Switch>
16
+ </template>
17
+
18
+ <script setup>
19
+ import { ref } from "vue";
20
+ import { Switch } from "@phila/phila-ui-switch";
21
+
22
+ const isEnabled = ref(false);
23
+ </script>
24
+ ```
25
+
26
+ ## Props
27
+
28
+ | Prop | Type | Default | Description |
29
+ | ------------ | ----------------------------- | ---------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
30
+ | `id` | `string` | `generateRandomId("switch-input")` | Unique identifier (uses [generateRandomId](https://github.com/CityOfPhiladelphia/phila-ui-4/tree/main/packages/core#generateRandomId) from core) |
31
+ | `modelValue` | `string \| number \| boolean` | `false` | Current value (v-model) |
32
+ | `value` | `string \| number \| boolean` | `true` | Value when checked |
33
+ | `offValue` | `string \| number \| boolean` | `false` | Value when unchecked |
34
+ | `disabled` | `boolean` | `false` | Disable the switch |
35
+ | `name` | `string` | `"switch-input"` | Input name attribute |
36
+ | `autofocus` | `boolean` | `false` | Auto-focus on mount |
37
+ | `ariaLabel` | `string` | `"Switch input"` | Screen reader label |
38
+ | `className` | `string` | `undefined` | Additional CSS classes |
39
+
40
+ ## Events
41
+
42
+ | Event | Payload | Description |
43
+ | ------------------- | ---------------------------------------------------- | -------------- |
44
+ | `update:modelValue` | `(value: string \| number \| boolean)` | v-model update |
45
+ | `change` | `(value: string \| number \| boolean, event: Event)` | State change |
46
+ | `focus` | `(event: FocusEvent)` | Focus event |
47
+ | `blur` | `(event: FocusEvent)` | Blur event |
48
+
49
+ ## Examples
50
+
51
+ ### Custom Values
52
+
53
+ ```vue
54
+ <Switch v-model="status" :value="'active'" :off-value="'inactive'">
55
+ Status: {{ status }}
56
+ </Switch>
57
+ ```
58
+
59
+ ### Disabled
60
+
61
+ ```vue
62
+ <Switch v-model="isEnabled" disabled>Disabled switch</Switch>
63
+ ```
64
+
65
+ ## Development
66
+
67
+ ### Install Dependencies
68
+
69
+ ```bash
70
+ pnpm install
71
+ ```
72
+
73
+ ### Run Demo
74
+
75
+ ```bash
76
+ pnpm dev
77
+ ```
78
+
79
+ ### Build Library
80
+
81
+ ```bash
82
+ pnpm build
83
+ ```
84
+
85
+ ### Type Check
86
+
87
+ ```bash
88
+ pnpm type-check
89
+ ```
90
+
91
+ ## License
92
+
93
+ MIT
@@ -0,0 +1,45 @@
1
+ import { SwitchProps } from './index';
2
+ declare function __VLS_template(): {
3
+ attrs: Partial<{}>;
4
+ slots: {
5
+ default?(_: {}): any;
6
+ };
7
+ refs: {
8
+ inputRef: HTMLInputElement;
9
+ };
10
+ rootEl: HTMLLabelElement;
11
+ };
12
+ type __VLS_TemplateResult = ReturnType<typeof __VLS_template>;
13
+ declare const __VLS_component: import('vue').DefineComponent<SwitchProps, {
14
+ focus: () => Promise<void>;
15
+ blur: () => Promise<void>;
16
+ }, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
17
+ "update:modelValue": (value: string | number | boolean) => any;
18
+ change: (value: string | number | boolean, event: Event) => any;
19
+ focus: (event: FocusEvent) => any;
20
+ blur: (event: FocusEvent) => any;
21
+ }, string, import('vue').PublicProps, Readonly<SwitchProps> & Readonly<{
22
+ "onUpdate:modelValue"?: ((value: string | number | boolean) => any) | undefined;
23
+ onChange?: ((value: string | number | boolean, event: Event) => any) | undefined;
24
+ onFocus?: ((event: FocusEvent) => any) | undefined;
25
+ onBlur?: ((event: FocusEvent) => any) | undefined;
26
+ }>, {
27
+ id: string;
28
+ name: string;
29
+ modelValue: string | number | boolean;
30
+ disabled: boolean;
31
+ value: string | number | boolean;
32
+ offValue: string | number | boolean;
33
+ autofocus: boolean;
34
+ ariaLabel: string;
35
+ }, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {
36
+ inputRef: HTMLInputElement;
37
+ }, HTMLLabelElement>;
38
+ declare const _default: __VLS_WithTemplateSlots<typeof __VLS_component, __VLS_TemplateResult["slots"]>;
39
+ export default _default;
40
+ type __VLS_WithTemplateSlots<T, S> = T & {
41
+ new (): {
42
+ $slots: S;
43
+ };
44
+ };
45
+ //# sourceMappingURL=Switch.vue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Switch.vue.d.ts","sourceRoot":"","sources":["../src/Switch.vue"],"names":[],"mappings":"AAyMA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AA6F3C,iBAAS,cAAc;WAgET,OAAO,IAA6B;;yBAXrB,GAAG;;;;;;EAgB/B;AAiBD,KAAK,oBAAoB,GAAG,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC;AAC9D,QAAA,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;oBAWnB,CAAC;wBACkB,uBAAuB,CAAC,OAAO,eAAe,EAAE,oBAAoB,CAAC,OAAO,CAAC,CAAC;AAAnG,wBAAoG;AAapG,KAAK,uBAAuB,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG;IACxC,QAAO;QACN,MAAM,EAAE,CAAC,CAAC;KAEV,CAAA;CACD,CAAC"}
package/dist/index.css ADDED
@@ -0,0 +1 @@
1
+ .switch[data-v-752a1efa]{display:inline-flex;align-items:center;cursor:pointer;position:relative}.switch--disabled[data-v-752a1efa]{cursor:not-allowed;opacity:.6}.switch-input[data-v-752a1efa]{position:absolute;opacity:0;width:0;height:0;margin:0;padding:0;border:none;outline:none}.switch-track[data-v-752a1efa]{display:inline-block;position:relative;background:var(--Schemes-Surface-Container-Highest, #ababab);transition:background-color .2s ease;display:flex;width:2rem;height:1.125rem;padding:var(--scale-xxsmall, .125rem);justify-content:flex-end;align-items:center;border-radius:var(--Radius-scale-radius-xl, 2rem);box-sizing:border-box}.switch-thumb[data-v-752a1efa]{width:.875rem;height:.875rem;flex-shrink:0;background-color:var(--Schemes-On-Primary, #ffffff);border-radius:var(--Radius-scale-radius-xl, 2rem);box-sizing:border-box;position:absolute;top:50%;left:var(--scale-xxsmall, .125rem);transform:translateY(-50%);transition:transform .2s ease}.switch-label[data-v-752a1efa]{padding-left:var(--scale-small, .5rem);color:var(--Schemes-On-Surface, #000);font-family:var(--Body-Default-font-body-default-family, Montserrat);font-size:var(--Body-Default-font-body-default-size, 1rem);font-style:normal;font-weight:400;line-height:var(--Body-Default-font-body-default-lineheight, 1.5rem)}.switch--checked .switch-track[data-v-752a1efa]{background:var(--Schemes-Primary, #003282)}.switch--checked .switch-thumb[data-v-752a1efa]{transform:translateY(-50%) translate(calc(2rem - .875rem - var(--scale-xxsmall, .125rem) - var(--scale-xxsmall, .125rem)))}.switch-input:focus+.switch-track[data-v-752a1efa]{outline:2px solid var(--Schemes-Primary, #003282);outline-offset:2px}.switch--disabled .switch-track[data-v-752a1efa]{background:var(--Schemes-Surface-Container, #e2e2e2)}.switch--disabled .switch-thumb[data-v-752a1efa]{background-color:var(--Schemes-On-Inverse-Surface, #f1f1f1)}.switch--disabled .switch-label[data-v-752a1efa]{color:var(--Schemes-Surface-Container-Highest, #ababab)}
@@ -0,0 +1,13 @@
1
+ import { BaseProps } from '@phila/phila-ui-core';
2
+ export { default as Switch } from './Switch.vue';
3
+ export interface SwitchProps extends BaseProps {
4
+ id?: string;
5
+ name?: string;
6
+ modelValue?: string | number | boolean;
7
+ disabled?: boolean;
8
+ value?: string | number | boolean;
9
+ offValue?: string | number | boolean;
10
+ autofocus?: boolean;
11
+ ariaLabel?: string;
12
+ }
13
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,cAAc,CAAC;AAEjD,MAAM,WAAW,WAAY,SAAQ,SAAS;IAC5C,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;IACvC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;IAClC,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;IACrC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB"}
package/dist/index.js ADDED
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});require('./index.css');const e=require("vue"),r=require("@phila/phila-ui-core"),v=["for"],w=["id","name","checked","disabled","autofocus","aria-label","aria-labelledby","value"],y=["id"],V=e.defineComponent({__name:"Switch",props:{id:{default:()=>r.generateRandomId("switch-input")},name:{default:"switch-input"},modelValue:{type:[String,Number,Boolean],default:!1},disabled:{type:Boolean,default:!1},value:{type:[String,Number,Boolean],default:!0},offValue:{type:[String,Number,Boolean],default:!1},autofocus:{type:Boolean,default:!1},ariaLabel:{default:"Switch input"},className:{}},emits:["update:modelValue","change","focus","blur"],setup(a,{expose:u,emit:c}){const t=a,o=c,n=e.ref(),s=e.computed(()=>typeof t.modelValue=="boolean"?t.modelValue:t.modelValue===t.value),f=e.computed(()=>s.value?t.value:t.offValue),m=l=>{const i=l.target.checked?t.value:t.offValue;o("update:modelValue",i),o("change",i,l)},b=l=>{o("focus",l)},h=l=>{o("blur",l)};u({focus:async()=>{await e.nextTick(),n.value?.focus()},blur:async()=>{await e.nextTick(),n.value?.blur()}});const p=e.computed(()=>r.cn("switch",s.value&&"switch--checked",t.disabled&&"switch--disabled",t.className));return(l,d)=>(e.openBlock(),e.createElementBlock("label",{class:e.normalizeClass(p.value),for:a.id},[e.createElementVNode("input",{id:a.id,ref_key:"inputRef",ref:n,name:a.name,type:"checkbox",checked:s.value,disabled:a.disabled,autofocus:a.autofocus,"aria-label":a.ariaLabel,"aria-labelledby":`${a.id}-label`,value:f.value,class:"switch-input",onChange:m,onFocus:b,onBlur:h},null,40,w),d[0]||(d[0]=e.createElementVNode("span",{class:"switch-track"},[e.createElementVNode("span",{class:"switch-thumb"})],-1)),e.createElementVNode("span",{id:`${a.id}-label`,class:"switch-label"},[e.renderSlot(l.$slots,"default",{},void 0,!0)],8,y)],10,v))}}),g=(a,u)=>{const c=a.__vccOpts||a;for(const[t,o]of u)c[t]=o;return c},k=g(V,[["__scopeId","data-v-752a1efa"]]);exports.Switch=k;
package/dist/index.mjs ADDED
@@ -0,0 +1,75 @@
1
+ import { defineComponent as w, ref as y, computed as i, createElementBlock as g, openBlock as k, normalizeClass as V, createElementVNode as s, renderSlot as B, nextTick as f } from "vue";
2
+ import { generateRandomId as S, cn as N } from "@phila/phila-ui-core";
3
+ import './index.css';const x = ["for"], C = ["id", "name", "checked", "disabled", "autofocus", "aria-label", "aria-labelledby", "value"], R = ["id"], $ = /* @__PURE__ */ w({
4
+ __name: "Switch",
5
+ props: {
6
+ id: { default: () => S("switch-input") },
7
+ name: { default: "switch-input" },
8
+ modelValue: { type: [String, Number, Boolean], default: !1 },
9
+ disabled: { type: Boolean, default: !1 },
10
+ value: { type: [String, Number, Boolean], default: !0 },
11
+ offValue: { type: [String, Number, Boolean], default: !1 },
12
+ autofocus: { type: Boolean, default: !1 },
13
+ ariaLabel: { default: "Switch input" },
14
+ className: {}
15
+ },
16
+ emits: ["update:modelValue", "change", "focus", "blur"],
17
+ setup(e, { expose: u, emit: o }) {
18
+ const a = e, l = o, c = y(), n = i(() => typeof a.modelValue == "boolean" ? a.modelValue : a.modelValue === a.value), m = i(() => n.value ? a.value : a.offValue), b = (t) => {
19
+ const r = t.target.checked ? a.value : a.offValue;
20
+ l("update:modelValue", r), l("change", r, t);
21
+ }, h = (t) => {
22
+ l("focus", t);
23
+ }, p = (t) => {
24
+ l("blur", t);
25
+ };
26
+ u({
27
+ focus: async () => {
28
+ await f(), c.value?.focus();
29
+ },
30
+ blur: async () => {
31
+ await f(), c.value?.blur();
32
+ }
33
+ });
34
+ const v = i(() => N("switch", n.value && "switch--checked", a.disabled && "switch--disabled", a.className));
35
+ return (t, d) => (k(), g("label", {
36
+ class: V(v.value),
37
+ for: e.id
38
+ }, [
39
+ s("input", {
40
+ id: e.id,
41
+ ref_key: "inputRef",
42
+ ref: c,
43
+ name: e.name,
44
+ type: "checkbox",
45
+ checked: n.value,
46
+ disabled: e.disabled,
47
+ autofocus: e.autofocus,
48
+ "aria-label": e.ariaLabel,
49
+ "aria-labelledby": `${e.id}-label`,
50
+ value: m.value,
51
+ class: "switch-input",
52
+ onChange: b,
53
+ onFocus: h,
54
+ onBlur: p
55
+ }, null, 40, C),
56
+ d[0] || (d[0] = s("span", { class: "switch-track" }, [
57
+ s("span", { class: "switch-thumb" })
58
+ ], -1)),
59
+ s("span", {
60
+ id: `${e.id}-label`,
61
+ class: "switch-label"
62
+ }, [
63
+ B(t.$slots, "default", {}, void 0, !0)
64
+ ], 8, R)
65
+ ], 10, x));
66
+ }
67
+ }), E = (e, u) => {
68
+ const o = e.__vccOpts || e;
69
+ for (const [a, l] of u)
70
+ o[a] = l;
71
+ return o;
72
+ }, O = /* @__PURE__ */ E($, [["__scopeId", "data-v-752a1efa"]]);
73
+ export {
74
+ O as Switch
75
+ };
package/package.json ADDED
@@ -0,0 +1,52 @@
1
+ {
2
+ "name": "@phila/phila-ui-switch",
3
+ "version": "0.0.1-beta.2",
4
+ "type": "module",
5
+ "description": "City of Philadelphia switch input component",
6
+ "main": "./dist/index.js",
7
+ "module": "./dist/index.mjs",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.mjs",
13
+ "require": "./dist/index.js"
14
+ }
15
+ },
16
+ "files": [
17
+ "dist"
18
+ ],
19
+ "keywords": [
20
+ "ui",
21
+ "switch",
22
+ "vue",
23
+ "component"
24
+ ],
25
+ "author": "",
26
+ "license": "MIT",
27
+ "peerDependencies": {
28
+ "vue": "^3.0.0"
29
+ },
30
+ "dependencies": {
31
+ "@phila/phila-ui-core": "2.2.0-beta.2"
32
+ },
33
+ "devDependencies": {
34
+ "@types/node": "^24.0.0",
35
+ "@vitejs/plugin-vue": "^6.0.1",
36
+ "eslint": "^9.0.0",
37
+ "typescript": "^5.8.3",
38
+ "vite": "^7.0.6",
39
+ "vite-plugin-dts": "^4.5.4",
40
+ "vite-plugin-lib-inject-css": "^2.2.2"
41
+ },
42
+ "scripts": {
43
+ "build": "vite build",
44
+ "dev": "vite build --watch",
45
+ "lint": "eslint src --ext .ts,.tsx,.vue",
46
+ "lint:fix": "eslint src --ext .ts,.tsx,.vue --fix",
47
+ "type-check": "tsc --noEmit",
48
+ "clean": "rm -rf dist",
49
+ "format": "prettier --write .",
50
+ "format:check": "prettier --check ."
51
+ }
52
+ }