@phila/phila-ui-link 1.0.0-beta.0

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,150 @@
1
+ # Link Component
2
+
3
+ A versatile Vue 3 Link component with TypeScript support, Vue Router integration, and external link icon support.
4
+
5
+ ## Features
6
+
7
+ - 🎯 TypeScript support with full type definitions
8
+ - 🔗 Supports both Vue Router links and HTML anchor links
9
+ - 🌐 External link icon support via `isExternal` prop
10
+ - 🎨 Multiple variants and sizes
11
+ - ♿ Full accessibility support
12
+ - 🎭 Icon support (left, right, or icon-only)
13
+
14
+ ## Installation
15
+
16
+ ```bash
17
+ npm install @phila/phila-ui-link
18
+ # or
19
+ yarn add @phila/phila-ui-link
20
+ # or
21
+ pnpm add @phila/phila-ui-link
22
+ ```
23
+
24
+ ## Usage
25
+
26
+ ### Basic HTML Link
27
+
28
+ ```vue
29
+ <script setup lang="ts">
30
+ import { PhilaLink } from "@phila/phila-ui-link";
31
+ </script>
32
+
33
+ <template>
34
+ <PhilaLink href="https://www.phila.gov" text="Visit Philadelphia" />
35
+ </template>
36
+ ```
37
+
38
+ ### Vue Router Link
39
+
40
+ ```vue
41
+ <template>
42
+ <PhilaLink to="/dashboard" text="Go to Dashboard" />
43
+ </template>
44
+ ```
45
+
46
+ ### Links with External Icon
47
+
48
+ Add an external link icon to links that go to external domains by setting the `isExternal` prop:
49
+
50
+ ```vue
51
+ <template>
52
+ <!-- Link to external domain with icon -->
53
+ <PhilaLink href="https://www.google.com" text="Visit Google" isExternal />
54
+
55
+ <!-- Link to same domain without icon -->
56
+ <PhilaLink href="/about" text="About Us" />
57
+ </template>
58
+ ```
59
+
60
+ ## Props
61
+
62
+ | Prop | Type | Default | Description |
63
+ | ---------------- | --------------------------- | ----------- | ------------------------------------------------------------ |
64
+ | `to` | `RouteLocationRaw` | - | Vue Router route destination. Mutually exclusive with `href` |
65
+ | `href` | `string` | - | HTML anchor href attribute. Mutually exclusive with `to` |
66
+ | `text` | `string` | - | Link text content |
67
+ | `variant` | `'default' \| 'on-primary'` | `'default'` | Link variant style |
68
+ | `size` | `ComponentSize` | - | Link size |
69
+ | `disabled` | `boolean` | `false` | Whether the link is disabled |
70
+ | `target` | `string` | - | Link target (e.g., `_blank`) |
71
+ | `rel` | `string` | - | Link rel attribute |
72
+ | `iconDefinition` | `IconDefinition` | - | FontAwesome icon definition |
73
+ | `iconClass` | `string` | - | FontAwesome icon class name |
74
+ | `iconRight` | `boolean` | `false` | Position icon on the right |
75
+ | `iconOnly` | `boolean` | `false` | Show only icon (no text) |
76
+ | `isExternal` | `boolean` | `false` | Show external link icon |
77
+ | `ariaLabel` | `string` | - | Accessible label for screen readers (required for icon-only) |
78
+ | `className` | `string` | - | Additional CSS classes (from `BaseProps`) |
79
+
80
+ ## Examples
81
+
82
+ ### With Icons
83
+
84
+ ```vue
85
+ <template>
86
+ <!-- Icon on the left -->
87
+ <PhilaLink href="/" text="Home" :iconDefinition="faHome" />
88
+
89
+ <!-- Icon on the right -->
90
+ <PhilaLink href="/next" text="Continue" :iconDefinition="faArrowRight" iconRight />
91
+
92
+ <!-- Icon only (requires ariaLabel for accessibility) -->
93
+ <PhilaLink href="/settings" :iconDefinition="faGear" iconOnly ariaLabel="Settings" />
94
+ </template>
95
+ ```
96
+
97
+ ### Links with Target Attribute
98
+
99
+ ```vue
100
+ <template>
101
+ <PhilaLink href="https://example.com" text="Open in New Tab" target="_blank" rel="noopener noreferrer" />
102
+ </template>
103
+ ```
104
+
105
+ ### Different Sizes
106
+
107
+ ```vue
108
+ <template>
109
+ <PhilaLink href="/" text="Large Link" size="large" />
110
+ <PhilaLink href="/" text="Small Link" size="small" />
111
+ </template>
112
+ ```
113
+
114
+ ### Disabled State
115
+
116
+ ```vue
117
+ <template>
118
+ <PhilaLink href="/" text="Disabled Link" disabled />
119
+ </template>
120
+ ```
121
+
122
+ ## Development
123
+
124
+ ### Install Dependencies
125
+
126
+ ```bash
127
+ pnpm install
128
+ ```
129
+
130
+ ### Run Demo
131
+
132
+ ```bash
133
+ pnpm dev
134
+ ```
135
+
136
+ ### Build Library
137
+
138
+ ```bash
139
+ pnpm build
140
+ ```
141
+
142
+ ### Type Check
143
+
144
+ ```bash
145
+ pnpm type-check
146
+ ```
147
+
148
+ ## License
149
+
150
+ MIT
@@ -0,0 +1,18 @@
1
+ declare function __VLS_template(): {
2
+ attrs: Partial<{}>;
3
+ slots: {
4
+ default?(_: {}): any;
5
+ };
6
+ refs: {};
7
+ rootEl: any;
8
+ };
9
+ type __VLS_TemplateResult = ReturnType<typeof __VLS_template>;
10
+ declare const __VLS_component: import('vue').DefineSetupFnComponent<Record<string, any>, {}, {}, Record<string, any> & {}, import('vue').PublicProps>;
11
+ declare const _default: __VLS_WithTemplateSlots<typeof __VLS_component, __VLS_TemplateResult["slots"]>;
12
+ export default _default;
13
+ type __VLS_WithTemplateSlots<T, S> = T & {
14
+ new (): {
15
+ $slots: S;
16
+ };
17
+ };
18
+ //# sourceMappingURL=Link.vue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Link.vue.d.ts","sourceRoot":"","sources":["../src/Link.vue"],"names":[],"mappings":"AAoLA,iBAAS,cAAc;WA4CT,OAAO,IAA6B;;yBAVpB,GAAG;;;;EAehC;AAaD,KAAK,oBAAoB,GAAG,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC;AAC9D,QAAA,MAAM,eAAe,wHAOnB,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"}
@@ -0,0 +1,17 @@
1
+ import { ActionContentProps, RouterLinkProps as BaseRouterLinkProps, HtmlLinkProps as BaseHtmlLinkProps } from '@phila/phila-ui-core';
2
+ export { default as PhilaLink } from './Link.vue';
3
+ export type LinkProps = RouterLinkProps | HtmlLinkProps;
4
+ export type LinkVariant = "default" | "on-primary";
5
+ interface LinkSpecificProps {
6
+ /** Link variant type */
7
+ variant?: LinkVariant;
8
+ /** Show external link icon (for links to external sites) */
9
+ isExternal?: boolean;
10
+ /** Accessible label for screen readers (required for icon-only links) */
11
+ ariaLabel?: string;
12
+ }
13
+ export interface RouterLinkProps extends BaseRouterLinkProps, ActionContentProps, LinkSpecificProps {
14
+ }
15
+ export interface HtmlLinkProps extends BaseHtmlLinkProps, ActionContentProps, LinkSpecificProps {
16
+ }
17
+ //# 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,EACV,kBAAkB,EAClB,eAAe,IAAI,mBAAmB,EACtC,aAAa,IAAI,iBAAiB,EACnC,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,YAAY,CAAC;AAElD,MAAM,MAAM,SAAS,GAAG,eAAe,GAAG,aAAa,CAAC;AAExD,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,YAAY,CAAC;AAEnD,UAAU,iBAAiB;IACzB,wBAAwB;IACxB,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB,4DAA4D;IAC5D,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,yEAAyE;IACzE,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,eAAgB,SAAQ,mBAAmB,EAAE,kBAAkB,EAAE,iBAAiB;CAAG;AAEtG,MAAM,WAAW,aAAc,SAAQ,iBAAiB,EAAE,kBAAkB,EAAE,iBAAiB;CAAG"}
package/dist/index.js ADDED
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("vue"),a=require("@phila/phila-ui-core"),c=t.defineComponent({inheritAttrs:!1,__name:"Link",props:{to:{},href:{},target:{},rel:{},disabled:{type:Boolean,default:!1},ariaLabel:{},className:{},iconRight:{type:Boolean},iconOnly:{type:Boolean,default:!1},text:{},size:{},iconDefinition:{},iconClass:{},src:{},svgRaw:{},variant:{default:"default"},isExternal:{type:Boolean,default:!1}},setup(o){const e=o,n=t.computed(()=>!(!e.isExternal||e.iconDefinition||e.iconClass||e.src||e.svgRaw)),s=t.computed(()=>a.cn("phila-link",e.variant&&`phila-link--${e.variant}`,e.size&&`is-${e.size}`,e.iconOnly&&"icon-link",e.disabled&&"is-disabled",e.className)),r=t.computed(()=>{const i={disabled:e.disabled,ariaLabel:e.ariaLabel,className:s.value};return a.isRouterLink(e)?{to:e.to,...i}:{href:e.href,target:e.target,rel:e.rel,...i}}),l=t.computed(()=>({iconDefinition:e.iconDefinition,iconClass:e.iconClass||(n.value?"external-link":void 0),src:e.src,svgRaw:e.svgRaw,iconRight:n.value?!0:e.iconRight,iconOnly:e.iconOnly,text:e.text,size:e.size}));return(i,u)=>(t.openBlock(),t.createBlock(t.unref(a.BaseLink),t.normalizeProps(t.guardReactiveProps({...r.value,...i.$attrs})),{default:t.withCtx(()=>[t.createVNode(t.unref(a.ActionContent),t.normalizeProps(t.guardReactiveProps(l.value)),{default:t.withCtx(()=>[t.renderSlot(i.$slots,"default",{},()=>[t.createTextVNode(t.toDisplayString(e.text),1)])]),_:3},16)]),_:3},16))}});exports.PhilaLink=c;
package/dist/index.mjs ADDED
@@ -0,0 +1,77 @@
1
+ import { defineComponent as d, computed as a, createBlock as p, openBlock as h, unref as i, normalizeProps as s, guardReactiveProps as o, withCtx as l, createVNode as v, renderSlot as g, createTextVNode as k, toDisplayString as m } from "vue";
2
+ import { cn as b, isRouterLink as x, BaseLink as y, ActionContent as R } from "@phila/phila-ui-core";
3
+ const w = /* @__PURE__ */ d({
4
+ inheritAttrs: !1,
5
+ __name: "Link",
6
+ props: {
7
+ to: {},
8
+ href: {},
9
+ target: {},
10
+ rel: {},
11
+ disabled: { type: Boolean, default: !1 },
12
+ ariaLabel: {},
13
+ className: {},
14
+ iconRight: { type: Boolean },
15
+ iconOnly: { type: Boolean, default: !1 },
16
+ text: {},
17
+ size: {},
18
+ iconDefinition: {},
19
+ iconClass: {},
20
+ src: {},
21
+ svgRaw: {},
22
+ variant: { default: "default" },
23
+ isExternal: { type: Boolean, default: !1 }
24
+ },
25
+ setup(r) {
26
+ const e = r, n = a(() => !(!e.isExternal || e.iconDefinition || e.iconClass || e.src || e.svgRaw)), c = a(() => b(
27
+ "phila-link",
28
+ e.variant && `phila-link--${e.variant}`,
29
+ e.size && `is-${e.size}`,
30
+ e.iconOnly && "icon-link",
31
+ e.disabled && "is-disabled",
32
+ e.className
33
+ )), f = a(() => {
34
+ const t = {
35
+ disabled: e.disabled,
36
+ ariaLabel: e.ariaLabel,
37
+ className: c.value
38
+ };
39
+ return x(e) ? {
40
+ to: e.to,
41
+ ...t
42
+ } : {
43
+ href: e.href,
44
+ target: e.target,
45
+ rel: e.rel,
46
+ ...t
47
+ };
48
+ }), u = a(
49
+ () => ({
50
+ iconDefinition: e.iconDefinition,
51
+ iconClass: e.iconClass || (n.value ? "external-link" : void 0),
52
+ src: e.src,
53
+ svgRaw: e.svgRaw,
54
+ iconRight: n.value ? !0 : e.iconRight,
55
+ iconOnly: e.iconOnly,
56
+ text: e.text,
57
+ size: e.size
58
+ })
59
+ );
60
+ return (t, C) => (h(), p(i(y), s(o({ ...f.value, ...t.$attrs })), {
61
+ default: l(() => [
62
+ v(i(R), s(o(u.value)), {
63
+ default: l(() => [
64
+ g(t.$slots, "default", {}, () => [
65
+ k(m(e.text), 1)
66
+ ])
67
+ ]),
68
+ _: 3
69
+ }, 16)
70
+ ]),
71
+ _: 3
72
+ }, 16));
73
+ }
74
+ });
75
+ export {
76
+ w as PhilaLink
77
+ };
package/package.json ADDED
@@ -0,0 +1,61 @@
1
+ {
2
+ "name": "@phila/phila-ui-link",
3
+ "version": "1.0.0-beta.0",
4
+ "type": "module",
5
+ "description": "Link component with suppport for Vue Router",
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
+ "link",
22
+ "vue",
23
+ "component"
24
+ ],
25
+ "author": "",
26
+ "license": "MIT",
27
+ "peerDependencies": {
28
+ "vue": "^3.0.0",
29
+ "vue-router": "^4.0.0",
30
+ "@fortawesome/fontawesome-svg-core": "^7.1.0",
31
+ "@fortawesome/vue-fontawesome": "^3.1.2"
32
+ },
33
+ "peerDependenciesMeta": {
34
+ "vue-router": {
35
+ "optional": true
36
+ }
37
+ },
38
+ "dependencies": {
39
+ "@phila/phila-ui-core": "2.2.0-beta.2"
40
+ },
41
+ "devDependencies": {
42
+ "@types/node": "^24.0.0",
43
+ "@vitejs/plugin-vue": "^6.0.1",
44
+ "eslint": "^9.0.0",
45
+ "typescript": "^5.8.3",
46
+ "vite": "^7.0.6",
47
+ "vite-plugin-dts": "^4.5.4",
48
+ "vite-plugin-lib-inject-css": "^2.2.2"
49
+ },
50
+ "scripts": {
51
+ "build": "vite build",
52
+ "build-win": "vite build",
53
+ "dev": "vite build --watch",
54
+ "lint": "eslint src --ext .ts,.tsx,.vue",
55
+ "lint:fix": "eslint src --ext .ts,.tsx,.vue --fix",
56
+ "type-check": "tsc --noEmit",
57
+ "clean": "rm -rf dist",
58
+ "format": "prettier --write .",
59
+ "format:check": "prettier --check ."
60
+ }
61
+ }