@frontpanel/vue 0.0.0-stage → 0.1.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/LICENSE +21 -0
- package/README.md +96 -2
- package/dist/FpButton.vue.d.ts +21 -0
- package/dist/FpCap.vue.d.ts +25 -0
- package/dist/FpDevice.vue.d.ts +39 -0
- package/dist/FpGelButton.vue.d.ts +18 -0
- package/dist/FpHousing.vue.d.ts +18 -0
- package/dist/FpIcon.vue.d.ts +10 -0
- package/dist/FpLcd.vue.d.ts +18 -0
- package/dist/FpLcdLine.vue.d.ts +16 -0
- package/dist/FpLed.vue.d.ts +16 -0
- package/dist/FpScrew.vue.d.ts +3 -0
- package/dist/FpSilk.vue.d.ts +18 -0
- package/dist/FpWell.vue.d.ts +18 -0
- package/dist/FpWindow.vue.d.ts +38 -0
- package/dist/fit.d.ts +10 -0
- package/dist/icons.d.ts +7 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.js +681 -0
- package/package.json +54 -3
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Dulan Katukurundage
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,97 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @frontpanel/vue
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Vue 3 components for the Frontpanel early-2000s hardware skin: a device frame that can scale to
|
|
4
|
+
fit, windows, chrome and gel buttons, molded caps, LCD lines, LEDs and a pixel icon set. Behaviour
|
|
5
|
+
and ARIA come from [Reka UI](https://reka-ui.com); the look comes from
|
|
6
|
+
[`@frontpanel/css`](https://www.npmjs.com/package/@frontpanel/css).
|
|
7
|
+
|
|
8
|
+
The UI kit behind [WhatsTheNextChord](https://whatsthenextchord.com).
|
|
9
|
+
|
|
10
|
+
**[Documentation](https://dulandev.github.io/frontpanel/)**: guides, live demos, and every
|
|
11
|
+
component, class and token.
|
|
12
|
+
|
|
13
|
+
> `0.x`: props may still change between minor versions. Pin the version.
|
|
14
|
+
|
|
15
|
+
## Install
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm install @frontpanel/vue
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
It needs Vue 3.5 or later. `@frontpanel/css` comes with it; the components ship no CSS of their
|
|
22
|
+
own, so import the stylesheet once:
|
|
23
|
+
|
|
24
|
+
```ts
|
|
25
|
+
import '@frontpanel/css/index.css'
|
|
26
|
+
import '@frontpanel/css/fonts.css' // optional: the display and LCD fonts
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
With Tailwind 4, import `@frontpanel/css/tailwind.css` instead (see its README), and add an
|
|
30
|
+
`@source` line for this package. Tailwind doesn't scan `node_modules`, so without it the classes
|
|
31
|
+
the components use are never generated. Give the path from your CSS file:
|
|
32
|
+
|
|
33
|
+
```css
|
|
34
|
+
@source "../node_modules/@frontpanel/vue/dist";
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Example
|
|
38
|
+
|
|
39
|
+
```vue
|
|
40
|
+
<script setup lang="ts">
|
|
41
|
+
import { FpButton, FpDevice, FpGelButton, FpLcd, FpLcdLine, FpLed, FpWindow } from '@frontpanel/vue'
|
|
42
|
+
import { ref } from 'vue'
|
|
43
|
+
|
|
44
|
+
const playing = ref(false)
|
|
45
|
+
</script>
|
|
46
|
+
|
|
47
|
+
<template>
|
|
48
|
+
<FpDevice fit="width" :width="600">
|
|
49
|
+
<FpWindow title="Deck">
|
|
50
|
+
<FpLcd>
|
|
51
|
+
<FpLcdLine :text="playing ? 'PLAYING' : 'STOPPED'" ghost :cells="12" redraw />
|
|
52
|
+
</FpLcd>
|
|
53
|
+
<FpLed :lit="playing" color="amber" />
|
|
54
|
+
<FpButton :pressed="playing" @click="playing = !playing">
|
|
55
|
+
Play
|
|
56
|
+
</FpButton>
|
|
57
|
+
<FpGelButton>Save</FpGelButton>
|
|
58
|
+
</FpWindow>
|
|
59
|
+
</FpDevice>
|
|
60
|
+
</template>
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Components
|
|
64
|
+
|
|
65
|
+
| Component | What it is |
|
|
66
|
+
| --- | --- |
|
|
67
|
+
| `FpDevice` | The device: a molded body in a liquid-chrome rim on a backdrop. `fit="width"` or `"contain"` draws it at a design `width` and scales it to the room it has; the default `fit="none"` leaves layout to your page |
|
|
68
|
+
| `FpWindow` | A matte module with a chrome title bar: `title`, `level`, `closable` (emits `close`), an `actions` slot, and `sheet` for a phone bottom sheet |
|
|
69
|
+
| `FpButton` | A brushed-chrome push button; `pressed` makes it a toggle |
|
|
70
|
+
| `FpGelButton` | The glossy gel pill, for the panel's main action |
|
|
71
|
+
| `FpCap` | A molded-plastic cap in `white`, `blue`, `amber`, `graphite` or `berry`; `pressed` holds it down with a ring |
|
|
72
|
+
| `FpLcd`, `FpLcdLine` | LCD glass, and a line of text on it with optional unlit segments (`ghost`, `cells`) and a left-to-right `redraw` |
|
|
73
|
+
| `FpLed` | A `green`, `amber` or `red` LED; `lit`, and `blink` to confirm an action |
|
|
74
|
+
| `FpHousing`, `FpWell`, `FpSilk`, `FpScrew` | A dark housing for LEDs, a recessed well, a silkscreened label, a screw head |
|
|
75
|
+
| `FpIcon` | An 18-glyph 16 px pixel icon set (`fpIconNames`) |
|
|
76
|
+
|
|
77
|
+
Element components take Reka's `as` and `asChild`.
|
|
78
|
+
|
|
79
|
+
## Accessibility
|
|
80
|
+
|
|
81
|
+
- **LEDs and icons are decorative** (`aria-hidden`) unless you give them a `label`, which makes
|
|
82
|
+
them an image with that name. Say an LED's state in text nearby, or label it; colour alone
|
|
83
|
+
never carries meaning.
|
|
84
|
+
- **An icon-only button needs a name.** Put `aria-label` on the `FpButton` and leave the
|
|
85
|
+
`FpIcon` inside it decorative.
|
|
86
|
+
- **`pressed` makes a toggle.** On `FpButton` and `FpCap` it sets `aria-pressed` and holds the
|
|
87
|
+
control down; leave it unset for an ordinary button, which then gets no `aria-pressed`.
|
|
88
|
+
- **Closing an `FpWindow` removes the focused close button.** Move focus back to the control
|
|
89
|
+
that opened the window.
|
|
90
|
+
- **`FpSilk` is a span.** Render it as a heading or `label` (`as="h3"`, `as="label"`) where it
|
|
91
|
+
names something.
|
|
92
|
+
- Every control shows a focus ring, every text colour pairing passes WCAG AA in both skins, and
|
|
93
|
+
each moving part respects `prefers-reduced-motion`.
|
|
94
|
+
|
|
95
|
+
## Licence
|
|
96
|
+
|
|
97
|
+
MIT.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { PrimitiveProps } from 'reka-ui';
|
|
2
|
+
export interface FpButtonProps extends PrimitiveProps {
|
|
3
|
+
/** Holds the button down and sets `aria-pressed`, for a toggle. Leave it unset for a plain push button. */
|
|
4
|
+
pressed?: boolean;
|
|
5
|
+
}
|
|
6
|
+
declare var __VLS_7: {};
|
|
7
|
+
type __VLS_Slots = {} & {
|
|
8
|
+
default?: (props: typeof __VLS_7) => any;
|
|
9
|
+
};
|
|
10
|
+
declare const __VLS_base: import("vue").DefineComponent<FpButtonProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<FpButtonProps> & Readonly<{}>, {
|
|
11
|
+
pressed: boolean;
|
|
12
|
+
as: import("reka-ui").AsTag | import("vue").Component;
|
|
13
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
14
|
+
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
15
|
+
declare const _default: typeof __VLS_export;
|
|
16
|
+
export default _default;
|
|
17
|
+
type __VLS_WithSlots<T, S> = T & {
|
|
18
|
+
new (): {
|
|
19
|
+
$slots: S;
|
|
20
|
+
};
|
|
21
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { PrimitiveProps } from 'reka-ui';
|
|
2
|
+
export type FpCapColor = 'white' | 'blue' | 'amber' | 'graphite' | 'berry';
|
|
3
|
+
export interface FpCapProps extends PrimitiveProps {
|
|
4
|
+
/** The plastic. Each colour carries its own label colour. */
|
|
5
|
+
color?: FpCapColor;
|
|
6
|
+
/** Holds the cap down with a ring around it and sets `aria-pressed`. Leave it unset for a plain cap. */
|
|
7
|
+
pressed?: boolean;
|
|
8
|
+
}
|
|
9
|
+
declare var __VLS_7: {};
|
|
10
|
+
type __VLS_Slots = {} & {
|
|
11
|
+
default?: (props: typeof __VLS_7) => any;
|
|
12
|
+
};
|
|
13
|
+
declare const __VLS_base: import("vue").DefineComponent<FpCapProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<FpCapProps> & Readonly<{}>, {
|
|
14
|
+
pressed: boolean;
|
|
15
|
+
as: import("reka-ui").AsTag | import("vue").Component;
|
|
16
|
+
color: FpCapColor;
|
|
17
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
18
|
+
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
19
|
+
declare const _default: typeof __VLS_export;
|
|
20
|
+
export default _default;
|
|
21
|
+
type __VLS_WithSlots<T, S> = T & {
|
|
22
|
+
new (): {
|
|
23
|
+
$slots: S;
|
|
24
|
+
};
|
|
25
|
+
};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { FpDeviceFit } from './fit';
|
|
2
|
+
export interface FpDeviceProps {
|
|
3
|
+
/** Sets the device on the gridded backdrop. Turn it off when the page already provides one. */
|
|
4
|
+
backdrop?: boolean;
|
|
5
|
+
/** Rings the body in liquid chrome. Without it the body runs to the edges, as on a phone. */
|
|
6
|
+
rim?: boolean;
|
|
7
|
+
/**
|
|
8
|
+
* Scale-to-fit. `none` leaves layout to the page: the device fills its box and its modules reflow
|
|
9
|
+
* at your breakpoints. `width` draws the device at its design `width` and scales it to the width it
|
|
10
|
+
* has; `contain` scales it to fit both sides, which needs a box with a height of its own.
|
|
11
|
+
*/
|
|
12
|
+
fit?: FpDeviceFit;
|
|
13
|
+
/** The design width in px, rim included, which scale-to-fit needs. */
|
|
14
|
+
width?: number;
|
|
15
|
+
/** A fixed design height in px. Without it the device is as tall as its contents. */
|
|
16
|
+
height?: number;
|
|
17
|
+
/** The largest scale to-fit may reach. 1 keeps the device from growing past its design size. */
|
|
18
|
+
maxScale?: number;
|
|
19
|
+
}
|
|
20
|
+
declare var __VLS_1: {}, __VLS_3: {};
|
|
21
|
+
type __VLS_Slots = {} & {
|
|
22
|
+
default?: (props: typeof __VLS_1) => any;
|
|
23
|
+
} & {
|
|
24
|
+
default?: (props: typeof __VLS_3) => any;
|
|
25
|
+
};
|
|
26
|
+
declare const __VLS_base: import("vue").DefineComponent<FpDeviceProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<FpDeviceProps> & Readonly<{}>, {
|
|
27
|
+
backdrop: boolean;
|
|
28
|
+
rim: boolean;
|
|
29
|
+
fit: FpDeviceFit;
|
|
30
|
+
maxScale: number;
|
|
31
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
32
|
+
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
33
|
+
declare const _default: typeof __VLS_export;
|
|
34
|
+
export default _default;
|
|
35
|
+
type __VLS_WithSlots<T, S> = T & {
|
|
36
|
+
new (): {
|
|
37
|
+
$slots: S;
|
|
38
|
+
};
|
|
39
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { PrimitiveProps } from 'reka-ui';
|
|
2
|
+
export interface FpGelButtonProps extends PrimitiveProps {
|
|
3
|
+
}
|
|
4
|
+
declare var __VLS_7: {};
|
|
5
|
+
type __VLS_Slots = {} & {
|
|
6
|
+
default?: (props: typeof __VLS_7) => any;
|
|
7
|
+
};
|
|
8
|
+
declare const __VLS_base: import("vue").DefineComponent<FpGelButtonProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<FpGelButtonProps> & Readonly<{}>, {
|
|
9
|
+
as: import("reka-ui").AsTag | import("vue").Component;
|
|
10
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
11
|
+
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
12
|
+
declare const _default: typeof __VLS_export;
|
|
13
|
+
export default _default;
|
|
14
|
+
type __VLS_WithSlots<T, S> = T & {
|
|
15
|
+
new (): {
|
|
16
|
+
$slots: S;
|
|
17
|
+
};
|
|
18
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { PrimitiveProps } from 'reka-ui';
|
|
2
|
+
export interface FpHousingProps extends PrimitiveProps {
|
|
3
|
+
}
|
|
4
|
+
declare var __VLS_7: {};
|
|
5
|
+
type __VLS_Slots = {} & {
|
|
6
|
+
default?: (props: typeof __VLS_7) => any;
|
|
7
|
+
};
|
|
8
|
+
declare const __VLS_base: import("vue").DefineComponent<FpHousingProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<FpHousingProps> & Readonly<{}>, {
|
|
9
|
+
as: import("reka-ui").AsTag | import("vue").Component;
|
|
10
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
11
|
+
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
12
|
+
declare const _default: typeof __VLS_export;
|
|
13
|
+
export default _default;
|
|
14
|
+
type __VLS_WithSlots<T, S> = T & {
|
|
15
|
+
new (): {
|
|
16
|
+
$slots: S;
|
|
17
|
+
};
|
|
18
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { FpIconName } from './icons';
|
|
2
|
+
export interface FpIconProps {
|
|
3
|
+
/** Which glyph, one of `fpIconNames`. */
|
|
4
|
+
name: FpIconName;
|
|
5
|
+
/** Announces the icon as an image with this name, for an icon that stands alone. */
|
|
6
|
+
label?: string;
|
|
7
|
+
}
|
|
8
|
+
declare const __VLS_export: import("vue").DefineComponent<FpIconProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<FpIconProps> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
9
|
+
declare const _default: typeof __VLS_export;
|
|
10
|
+
export default _default;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { PrimitiveProps } from 'reka-ui';
|
|
2
|
+
export interface FpLcdProps extends PrimitiveProps {
|
|
3
|
+
}
|
|
4
|
+
declare var __VLS_7: {};
|
|
5
|
+
type __VLS_Slots = {} & {
|
|
6
|
+
default?: (props: typeof __VLS_7) => any;
|
|
7
|
+
};
|
|
8
|
+
declare const __VLS_base: import("vue").DefineComponent<FpLcdProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<FpLcdProps> & Readonly<{}>, {
|
|
9
|
+
as: import("reka-ui").AsTag | import("vue").Component;
|
|
10
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
11
|
+
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
12
|
+
declare const _default: typeof __VLS_export;
|
|
13
|
+
export default _default;
|
|
14
|
+
type __VLS_WithSlots<T, S> = T & {
|
|
15
|
+
new (): {
|
|
16
|
+
$slots: S;
|
|
17
|
+
};
|
|
18
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { PrimitiveProps } from 'reka-ui';
|
|
2
|
+
export interface FpLcdLineProps extends PrimitiveProps {
|
|
3
|
+
/** The text on the glass. Readouts read best in capitals. */
|
|
4
|
+
text: string;
|
|
5
|
+
/** Shows the unlit segments behind the text, as on real glass. */
|
|
6
|
+
ghost?: boolean;
|
|
7
|
+
/** The line's width in character cells, which the ghost segments fill. Defaults to the text's length. */
|
|
8
|
+
cells?: number;
|
|
9
|
+
/** Redraws the line left to right whenever its text changes, as a display does. */
|
|
10
|
+
redraw?: boolean;
|
|
11
|
+
}
|
|
12
|
+
declare const __VLS_export: import("vue").DefineComponent<FpLcdLineProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<FpLcdLineProps> & Readonly<{}>, {
|
|
13
|
+
as: import("reka-ui").AsTag | import("vue").Component;
|
|
14
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
15
|
+
declare const _default: typeof __VLS_export;
|
|
16
|
+
export default _default;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export type FpLedColor = 'green' | 'amber' | 'red';
|
|
2
|
+
export interface FpLedProps {
|
|
3
|
+
/** The colour it lights in. */
|
|
4
|
+
color?: FpLedColor;
|
|
5
|
+
/** Lights the LED, with a glow. */
|
|
6
|
+
lit?: boolean;
|
|
7
|
+
/** Blinks twice when it lights, then holds, to confirm an action. Re-key the LED to blink again. */
|
|
8
|
+
blink?: boolean;
|
|
9
|
+
/** Announces the LED as an image with this name. Without it the LED is decorative: say its state in text nearby. */
|
|
10
|
+
label?: string;
|
|
11
|
+
}
|
|
12
|
+
declare const __VLS_export: import("vue").DefineComponent<FpLedProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<FpLedProps> & Readonly<{}>, {
|
|
13
|
+
color: FpLedColor;
|
|
14
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
15
|
+
declare const _default: typeof __VLS_export;
|
|
16
|
+
export default _default;
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
declare const __VLS_export: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
2
|
+
declare const _default: typeof __VLS_export;
|
|
3
|
+
export default _default;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { PrimitiveProps } from 'reka-ui';
|
|
2
|
+
export interface FpSilkProps extends PrimitiveProps {
|
|
3
|
+
}
|
|
4
|
+
declare var __VLS_7: {};
|
|
5
|
+
type __VLS_Slots = {} & {
|
|
6
|
+
default?: (props: typeof __VLS_7) => any;
|
|
7
|
+
};
|
|
8
|
+
declare const __VLS_base: import("vue").DefineComponent<FpSilkProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<FpSilkProps> & Readonly<{}>, {
|
|
9
|
+
as: import("reka-ui").AsTag | import("vue").Component;
|
|
10
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
11
|
+
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
12
|
+
declare const _default: typeof __VLS_export;
|
|
13
|
+
export default _default;
|
|
14
|
+
type __VLS_WithSlots<T, S> = T & {
|
|
15
|
+
new (): {
|
|
16
|
+
$slots: S;
|
|
17
|
+
};
|
|
18
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { PrimitiveProps } from 'reka-ui';
|
|
2
|
+
export interface FpWellProps extends PrimitiveProps {
|
|
3
|
+
}
|
|
4
|
+
declare var __VLS_7: {};
|
|
5
|
+
type __VLS_Slots = {} & {
|
|
6
|
+
default?: (props: typeof __VLS_7) => any;
|
|
7
|
+
};
|
|
8
|
+
declare const __VLS_base: import("vue").DefineComponent<FpWellProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<FpWellProps> & Readonly<{}>, {
|
|
9
|
+
as: import("reka-ui").AsTag | import("vue").Component;
|
|
10
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
11
|
+
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
12
|
+
declare const _default: typeof __VLS_export;
|
|
13
|
+
export default _default;
|
|
14
|
+
type __VLS_WithSlots<T, S> = T & {
|
|
15
|
+
new (): {
|
|
16
|
+
$slots: S;
|
|
17
|
+
};
|
|
18
|
+
};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
export interface FpWindowProps {
|
|
2
|
+
/** The window's name, shown in the title bar; it also names the window for assistive tech. */
|
|
3
|
+
title: string;
|
|
4
|
+
/** The title's heading level. */
|
|
5
|
+
level?: 2 | 3 | 4 | 5 | 6;
|
|
6
|
+
/**
|
|
7
|
+
* Adds a close button to the title bar, which emits `close`. Closing removes the focused button, so
|
|
8
|
+
* move focus back to the control that opened the window.
|
|
9
|
+
*/
|
|
10
|
+
closable?: boolean;
|
|
11
|
+
/** The close button's accessible name. Defaults to "Close" and the title. */
|
|
12
|
+
closeLabel?: string;
|
|
13
|
+
/**
|
|
14
|
+
* Wears the phone bottom sheet (`fp-sheet-panel`, in the opt-in page extra) instead of the module.
|
|
15
|
+
* Position the sheet and choose when to use it yourself; wrap it in `<Transition name="fp-sheet">`.
|
|
16
|
+
*/
|
|
17
|
+
sheet?: boolean;
|
|
18
|
+
}
|
|
19
|
+
type __VLS_Slots = {
|
|
20
|
+
default?: () => unknown;
|
|
21
|
+
/** Extra title-bar buttons, set before the close button. */
|
|
22
|
+
actions?: () => unknown;
|
|
23
|
+
};
|
|
24
|
+
declare const __VLS_base: import("vue").DefineComponent<FpWindowProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
25
|
+
close: () => any;
|
|
26
|
+
}, string, import("vue").PublicProps, Readonly<FpWindowProps> & Readonly<{
|
|
27
|
+
onClose?: (() => any) | undefined;
|
|
28
|
+
}>, {
|
|
29
|
+
level: 2 | 3 | 4 | 5 | 6;
|
|
30
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
31
|
+
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
32
|
+
declare const _default: typeof __VLS_export;
|
|
33
|
+
export default _default;
|
|
34
|
+
type __VLS_WithSlots<T, S> = T & {
|
|
35
|
+
new (): {
|
|
36
|
+
$slots: S;
|
|
37
|
+
};
|
|
38
|
+
};
|
package/dist/fit.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export type FpDeviceFit = 'none' | 'width' | 'contain';
|
|
2
|
+
export interface Size {
|
|
3
|
+
width: number;
|
|
4
|
+
height: number;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* The scale that fits a device of its design size into the room it has: to the width, or (contain)
|
|
8
|
+
* to whichever side runs out first. Null until both sides it needs are measurable.
|
|
9
|
+
*/
|
|
10
|
+
export declare function fitScale(fit: Exclude<FpDeviceFit, 'none'>, room: Size, device: Size, maxScale: number): number | null;
|
package/dist/icons.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export type FpIconName = 'add' | 'saved' | 'settings' | 'help' | 'home' | 'undo' | 'redo' | 'save' | 'copy' | 'trash' | 'close' | 'grip' | 'left' | 'right' | 'quick' | 'grid' | 'go' | 'menu';
|
|
2
|
+
/** One path per glyph: every horizontal run of lit pixels becomes a 1 px tall rectangle. */
|
|
3
|
+
export declare function toPath(rows: readonly string[]): string;
|
|
4
|
+
/** Every icon name, in the order the set lists them. */
|
|
5
|
+
export declare const fpIconNames: FpIconName[];
|
|
6
|
+
/** The SVG path of each icon, on a 16 × 16 viewBox. */
|
|
7
|
+
export declare const fpIconPaths: Record<FpIconName, string>;
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export type { FpDeviceFit } from './fit';
|
|
2
|
+
export { default as FpButton } from './FpButton.vue';
|
|
3
|
+
export type { FpButtonProps } from './FpButton.vue';
|
|
4
|
+
export { default as FpCap } from './FpCap.vue';
|
|
5
|
+
export type { FpCapColor, FpCapProps } from './FpCap.vue';
|
|
6
|
+
export { default as FpDevice } from './FpDevice.vue';
|
|
7
|
+
export type { FpDeviceProps } from './FpDevice.vue';
|
|
8
|
+
export { default as FpGelButton } from './FpGelButton.vue';
|
|
9
|
+
export type { FpGelButtonProps } from './FpGelButton.vue';
|
|
10
|
+
export { default as FpHousing } from './FpHousing.vue';
|
|
11
|
+
export type { FpHousingProps } from './FpHousing.vue';
|
|
12
|
+
export { default as FpIcon } from './FpIcon.vue';
|
|
13
|
+
export type { FpIconProps } from './FpIcon.vue';
|
|
14
|
+
export { default as FpLcd } from './FpLcd.vue';
|
|
15
|
+
export type { FpLcdProps } from './FpLcd.vue';
|
|
16
|
+
export { default as FpLcdLine } from './FpLcdLine.vue';
|
|
17
|
+
export type { FpLcdLineProps } from './FpLcdLine.vue';
|
|
18
|
+
export { default as FpLed } from './FpLed.vue';
|
|
19
|
+
export type { FpLedColor, FpLedProps } from './FpLed.vue';
|
|
20
|
+
export { default as FpScrew } from './FpScrew.vue';
|
|
21
|
+
export { default as FpSilk } from './FpSilk.vue';
|
|
22
|
+
export type { FpSilkProps } from './FpSilk.vue';
|
|
23
|
+
export { default as FpWell } from './FpWell.vue';
|
|
24
|
+
export type { FpWellProps } from './FpWell.vue';
|
|
25
|
+
export { default as FpWindow } from './FpWindow.vue';
|
|
26
|
+
export type { FpWindowProps } from './FpWindow.vue';
|
|
27
|
+
export { fpIconNames } from './icons';
|
|
28
|
+
export type { FpIconName } from './icons';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,681 @@
|
|
|
1
|
+
import { computed as e, createBlock as t, createCommentVNode as n, createElementBlock as r, createElementVNode as i, createTextVNode as a, createVNode as o, defineComponent as s, normalizeClass as c, normalizeStyle as l, openBlock as u, renderSlot as d, resolveDynamicComponent as f, shallowRef as p, toDisplayString as m, unref as h, useId as g, useTemplateRef as _, warn as v, watch as y, withCtx as b } from "vue";
|
|
2
|
+
import { Primitive as x } from "reka-ui";
|
|
3
|
+
//#endregion
|
|
4
|
+
//#region src/FpButton.vue
|
|
5
|
+
var S = /* @__PURE__ */ s({
|
|
6
|
+
__name: "FpButton",
|
|
7
|
+
props: {
|
|
8
|
+
pressed: {
|
|
9
|
+
type: Boolean,
|
|
10
|
+
default: void 0
|
|
11
|
+
},
|
|
12
|
+
asChild: { type: Boolean },
|
|
13
|
+
as: { default: "button" }
|
|
14
|
+
},
|
|
15
|
+
setup(e) {
|
|
16
|
+
let n = e;
|
|
17
|
+
return (e, r) => (u(), t(h(x), {
|
|
18
|
+
as: n.as,
|
|
19
|
+
"as-child": n.asChild,
|
|
20
|
+
class: "fp-chrome-btn",
|
|
21
|
+
type: n.as === "button" && !n.asChild ? "button" : void 0,
|
|
22
|
+
"aria-pressed": n.pressed
|
|
23
|
+
}, {
|
|
24
|
+
default: b(() => [d(e.$slots, "default")]),
|
|
25
|
+
_: 3
|
|
26
|
+
}, 8, [
|
|
27
|
+
"as",
|
|
28
|
+
"as-child",
|
|
29
|
+
"type",
|
|
30
|
+
"aria-pressed"
|
|
31
|
+
]));
|
|
32
|
+
}
|
|
33
|
+
}), C = /* @__PURE__ */ s({
|
|
34
|
+
__name: "FpCap",
|
|
35
|
+
props: {
|
|
36
|
+
color: { default: "white" },
|
|
37
|
+
pressed: {
|
|
38
|
+
type: Boolean,
|
|
39
|
+
default: void 0
|
|
40
|
+
},
|
|
41
|
+
asChild: { type: Boolean },
|
|
42
|
+
as: { default: "button" }
|
|
43
|
+
},
|
|
44
|
+
setup(e) {
|
|
45
|
+
let n = e, r = {
|
|
46
|
+
white: void 0,
|
|
47
|
+
blue: "fp-cap-blue",
|
|
48
|
+
amber: "fp-cap-amber",
|
|
49
|
+
graphite: "fp-cap-graphite",
|
|
50
|
+
berry: "fp-cap-berry"
|
|
51
|
+
};
|
|
52
|
+
return (e, i) => (u(), t(h(x), {
|
|
53
|
+
as: n.as,
|
|
54
|
+
"as-child": n.asChild,
|
|
55
|
+
class: c(["fp-cap", r[n.color]]),
|
|
56
|
+
type: n.as === "button" && !n.asChild ? "button" : void 0,
|
|
57
|
+
"aria-pressed": n.pressed
|
|
58
|
+
}, {
|
|
59
|
+
default: b(() => [d(e.$slots, "default")]),
|
|
60
|
+
_: 3
|
|
61
|
+
}, 8, [
|
|
62
|
+
"as",
|
|
63
|
+
"as-child",
|
|
64
|
+
"class",
|
|
65
|
+
"type",
|
|
66
|
+
"aria-pressed"
|
|
67
|
+
]));
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
//#endregion
|
|
71
|
+
//#region src/fit.ts
|
|
72
|
+
function w(e, t, n, r) {
|
|
73
|
+
if (t.width <= 0 || n.width <= 0) return null;
|
|
74
|
+
let i = t.width / n.width;
|
|
75
|
+
if (e === "contain") {
|
|
76
|
+
if (t.height <= 0 || n.height <= 0) return null;
|
|
77
|
+
i = Math.min(i, t.height / n.height);
|
|
78
|
+
}
|
|
79
|
+
return Math.min(i, r);
|
|
80
|
+
}
|
|
81
|
+
//#endregion
|
|
82
|
+
//#region src/FpDevice.vue?vue&type=script&setup=true&lang.ts
|
|
83
|
+
var T = { class: "fp-device-body" }, E = /* @__PURE__ */ s({
|
|
84
|
+
__name: "FpDevice",
|
|
85
|
+
props: {
|
|
86
|
+
backdrop: {
|
|
87
|
+
type: Boolean,
|
|
88
|
+
default: !0
|
|
89
|
+
},
|
|
90
|
+
rim: {
|
|
91
|
+
type: Boolean,
|
|
92
|
+
default: !0
|
|
93
|
+
},
|
|
94
|
+
fit: { default: "none" },
|
|
95
|
+
width: {},
|
|
96
|
+
height: {},
|
|
97
|
+
maxScale: { default: 1 }
|
|
98
|
+
},
|
|
99
|
+
setup(t) {
|
|
100
|
+
let n = t, a = _("stage"), o = _("device"), s = p({
|
|
101
|
+
width: 0,
|
|
102
|
+
height: 0
|
|
103
|
+
}), f = p(0), m = e(() => n.fit === "none" ? !1 : n.width !== void 0 || (v(`FpDevice: fit="${n.fit}" needs a design width; the device is not scaled.`), !1)), h = e(() => n.height ?? f.value), g = e(() => !m.value || n.fit === "none" ? null : w(n.fit, s.value, {
|
|
104
|
+
width: n.width,
|
|
105
|
+
height: h.value
|
|
106
|
+
}, n.maxScale));
|
|
107
|
+
function b() {
|
|
108
|
+
if (!a.value || !o.value) return;
|
|
109
|
+
let e = getComputedStyle(a.value), t = (e) => Number.parseFloat(e) || 0;
|
|
110
|
+
s.value = {
|
|
111
|
+
width: a.value.clientWidth - t(e.paddingLeft) - t(e.paddingRight),
|
|
112
|
+
height: a.value.clientHeight - t(e.paddingTop) - t(e.paddingBottom)
|
|
113
|
+
}, f.value = o.value.offsetHeight;
|
|
114
|
+
}
|
|
115
|
+
y([
|
|
116
|
+
m,
|
|
117
|
+
a,
|
|
118
|
+
o
|
|
119
|
+
], ([e, t, n], r, i) => {
|
|
120
|
+
if (!e || !t || !n || typeof ResizeObserver > "u") return;
|
|
121
|
+
let a = new ResizeObserver(b);
|
|
122
|
+
a.observe(t), a.observe(n), i(() => a.disconnect());
|
|
123
|
+
}, {
|
|
124
|
+
flush: "post",
|
|
125
|
+
immediate: !0
|
|
126
|
+
});
|
|
127
|
+
let x = e(() => m.value ? { contain: "inline-size" } : void 0), S = e(() => {
|
|
128
|
+
if (!m.value) return { display: "contents" };
|
|
129
|
+
if (g.value !== null) return {
|
|
130
|
+
width: `${n.width * g.value}px`,
|
|
131
|
+
height: `${h.value * g.value}px`,
|
|
132
|
+
marginInline: "auto"
|
|
133
|
+
};
|
|
134
|
+
}), C = e(() => {
|
|
135
|
+
if (m.value) return {
|
|
136
|
+
boxSizing: "border-box",
|
|
137
|
+
width: `${n.width}px`,
|
|
138
|
+
height: n.height === void 0 ? void 0 : `${n.height}px`,
|
|
139
|
+
scale: g.value ?? void 0,
|
|
140
|
+
transformOrigin: "0 0",
|
|
141
|
+
visibility: g.value === null ? "hidden" : void 0
|
|
142
|
+
};
|
|
143
|
+
});
|
|
144
|
+
return (e, t) => (u(), r("div", {
|
|
145
|
+
ref_key: "stage",
|
|
146
|
+
ref: a,
|
|
147
|
+
class: c({ "fp-device-backdrop": n.backdrop }),
|
|
148
|
+
style: l(x.value)
|
|
149
|
+
}, [i("div", { style: l(S.value) }, [n.rim ? (u(), r("div", {
|
|
150
|
+
key: 0,
|
|
151
|
+
ref_key: "device",
|
|
152
|
+
ref: o,
|
|
153
|
+
class: "fp-device-rim",
|
|
154
|
+
style: l(C.value)
|
|
155
|
+
}, [i("div", T, [d(e.$slots, "default")])], 4)) : (u(), r("div", {
|
|
156
|
+
key: 1,
|
|
157
|
+
ref_key: "device",
|
|
158
|
+
ref: o,
|
|
159
|
+
class: "fp-device-body",
|
|
160
|
+
style: l(C.value)
|
|
161
|
+
}, [d(e.$slots, "default")], 4))], 4)], 6));
|
|
162
|
+
}
|
|
163
|
+
}), D = /* @__PURE__ */ s({
|
|
164
|
+
__name: "FpGelButton",
|
|
165
|
+
props: {
|
|
166
|
+
asChild: { type: Boolean },
|
|
167
|
+
as: { default: "button" }
|
|
168
|
+
},
|
|
169
|
+
setup(e) {
|
|
170
|
+
let n = e;
|
|
171
|
+
return (e, r) => (u(), t(h(x), {
|
|
172
|
+
as: n.as,
|
|
173
|
+
"as-child": n.asChild,
|
|
174
|
+
class: "fp-gel",
|
|
175
|
+
type: n.as === "button" && !n.asChild ? "button" : void 0
|
|
176
|
+
}, {
|
|
177
|
+
default: b(() => [d(e.$slots, "default")]),
|
|
178
|
+
_: 3
|
|
179
|
+
}, 8, [
|
|
180
|
+
"as",
|
|
181
|
+
"as-child",
|
|
182
|
+
"type"
|
|
183
|
+
]));
|
|
184
|
+
}
|
|
185
|
+
}), O = /* @__PURE__ */ s({
|
|
186
|
+
__name: "FpHousing",
|
|
187
|
+
props: {
|
|
188
|
+
asChild: { type: Boolean },
|
|
189
|
+
as: { default: "span" }
|
|
190
|
+
},
|
|
191
|
+
setup(e) {
|
|
192
|
+
let n = e;
|
|
193
|
+
return (e, r) => (u(), t(h(x), {
|
|
194
|
+
as: n.as,
|
|
195
|
+
"as-child": n.asChild,
|
|
196
|
+
class: "fp-housing"
|
|
197
|
+
}, {
|
|
198
|
+
default: b(() => [d(e.$slots, "default")]),
|
|
199
|
+
_: 3
|
|
200
|
+
}, 8, ["as", "as-child"]));
|
|
201
|
+
}
|
|
202
|
+
}), k = [
|
|
203
|
+
"................",
|
|
204
|
+
"................",
|
|
205
|
+
".....#..........",
|
|
206
|
+
"....##..........",
|
|
207
|
+
"...##########...",
|
|
208
|
+
"..###########...",
|
|
209
|
+
"...##.......##..",
|
|
210
|
+
"....#........##.",
|
|
211
|
+
".............##.",
|
|
212
|
+
".............##.",
|
|
213
|
+
"............##..",
|
|
214
|
+
"...#########....",
|
|
215
|
+
"...########.....",
|
|
216
|
+
"................",
|
|
217
|
+
"................",
|
|
218
|
+
"................"
|
|
219
|
+
], A = [
|
|
220
|
+
"................",
|
|
221
|
+
"................",
|
|
222
|
+
".........##.....",
|
|
223
|
+
"........###.....",
|
|
224
|
+
".......###......",
|
|
225
|
+
"......###.......",
|
|
226
|
+
".....###........",
|
|
227
|
+
"....###.........",
|
|
228
|
+
"....###.........",
|
|
229
|
+
".....###........",
|
|
230
|
+
"......###.......",
|
|
231
|
+
".......###......",
|
|
232
|
+
"........###.....",
|
|
233
|
+
".........##.....",
|
|
234
|
+
"................",
|
|
235
|
+
"................"
|
|
236
|
+
], j = (e) => e.map((e) => [...e].reverse().join("")), M = {
|
|
237
|
+
add: [
|
|
238
|
+
"................",
|
|
239
|
+
"................",
|
|
240
|
+
".......##.......",
|
|
241
|
+
".......##.......",
|
|
242
|
+
".......##.......",
|
|
243
|
+
".......##.......",
|
|
244
|
+
".......##.......",
|
|
245
|
+
"..############..",
|
|
246
|
+
"..############..",
|
|
247
|
+
".......##.......",
|
|
248
|
+
".......##.......",
|
|
249
|
+
".......##.......",
|
|
250
|
+
".......##.......",
|
|
251
|
+
".......##.......",
|
|
252
|
+
"................",
|
|
253
|
+
"................"
|
|
254
|
+
],
|
|
255
|
+
close: [
|
|
256
|
+
"................",
|
|
257
|
+
"................",
|
|
258
|
+
"..##........##..",
|
|
259
|
+
"..###......###..",
|
|
260
|
+
"...###....###...",
|
|
261
|
+
"....###..###....",
|
|
262
|
+
".....######.....",
|
|
263
|
+
"......####......",
|
|
264
|
+
"......####......",
|
|
265
|
+
".....######.....",
|
|
266
|
+
"....###..###....",
|
|
267
|
+
"...###....###...",
|
|
268
|
+
"..###......###..",
|
|
269
|
+
"..##........##..",
|
|
270
|
+
"................",
|
|
271
|
+
"................"
|
|
272
|
+
],
|
|
273
|
+
left: A,
|
|
274
|
+
right: j(A),
|
|
275
|
+
go: [
|
|
276
|
+
"................",
|
|
277
|
+
"................",
|
|
278
|
+
"................",
|
|
279
|
+
".........##.....",
|
|
280
|
+
"..........##....",
|
|
281
|
+
"...........##...",
|
|
282
|
+
"............##..",
|
|
283
|
+
"..#############.",
|
|
284
|
+
"..#############.",
|
|
285
|
+
"............##..",
|
|
286
|
+
"...........##...",
|
|
287
|
+
"..........##....",
|
|
288
|
+
".........##.....",
|
|
289
|
+
"................",
|
|
290
|
+
"................",
|
|
291
|
+
"................"
|
|
292
|
+
],
|
|
293
|
+
undo: k,
|
|
294
|
+
redo: j(k),
|
|
295
|
+
home: [
|
|
296
|
+
"................",
|
|
297
|
+
".......##.......",
|
|
298
|
+
"......####......",
|
|
299
|
+
".....##..##.....",
|
|
300
|
+
"....##....##....",
|
|
301
|
+
"...##......##...",
|
|
302
|
+
"..##........##..",
|
|
303
|
+
".##..........##.",
|
|
304
|
+
"...#........#...",
|
|
305
|
+
"...#........#...",
|
|
306
|
+
"...#..###...#...",
|
|
307
|
+
"...#..#.#...#...",
|
|
308
|
+
"...#..#.#...#...",
|
|
309
|
+
"...#..#.#...#...",
|
|
310
|
+
"...##########...",
|
|
311
|
+
"................"
|
|
312
|
+
],
|
|
313
|
+
saved: [
|
|
314
|
+
"................",
|
|
315
|
+
"................",
|
|
316
|
+
"...##########...",
|
|
317
|
+
"...#........#...",
|
|
318
|
+
"...#........#...",
|
|
319
|
+
"...#........#...",
|
|
320
|
+
"...#........#...",
|
|
321
|
+
"...#........#...",
|
|
322
|
+
"...#........#...",
|
|
323
|
+
"...#........#...",
|
|
324
|
+
"...#...##...#...",
|
|
325
|
+
"...#..#..#..#...",
|
|
326
|
+
"...#.#....#.#...",
|
|
327
|
+
"...##......##...",
|
|
328
|
+
"................",
|
|
329
|
+
"................"
|
|
330
|
+
],
|
|
331
|
+
settings: [
|
|
332
|
+
"................",
|
|
333
|
+
"................",
|
|
334
|
+
"....##..........",
|
|
335
|
+
".##############.",
|
|
336
|
+
"....##..........",
|
|
337
|
+
"................",
|
|
338
|
+
"..........##....",
|
|
339
|
+
".##############.",
|
|
340
|
+
"..........##....",
|
|
341
|
+
"................",
|
|
342
|
+
"......##........",
|
|
343
|
+
".##############.",
|
|
344
|
+
"......##........",
|
|
345
|
+
"................",
|
|
346
|
+
"................",
|
|
347
|
+
"................"
|
|
348
|
+
],
|
|
349
|
+
help: [
|
|
350
|
+
"................",
|
|
351
|
+
"................",
|
|
352
|
+
".....######.....",
|
|
353
|
+
"....##....##....",
|
|
354
|
+
"....##....##....",
|
|
355
|
+
"..........##....",
|
|
356
|
+
".........##.....",
|
|
357
|
+
"........##......",
|
|
358
|
+
".......##.......",
|
|
359
|
+
".......##.......",
|
|
360
|
+
"................",
|
|
361
|
+
".......##.......",
|
|
362
|
+
".......##.......",
|
|
363
|
+
"................",
|
|
364
|
+
"................",
|
|
365
|
+
"................"
|
|
366
|
+
],
|
|
367
|
+
save: [
|
|
368
|
+
"................",
|
|
369
|
+
"................",
|
|
370
|
+
"..############..",
|
|
371
|
+
"..#..######..#..",
|
|
372
|
+
"..#..##..##..#..",
|
|
373
|
+
"..#..######..#..",
|
|
374
|
+
"..#..........#..",
|
|
375
|
+
"..#..........#..",
|
|
376
|
+
"..#.########.#..",
|
|
377
|
+
"..#.#......#.#..",
|
|
378
|
+
"..#.#......#.#..",
|
|
379
|
+
"..#.#......#.#..",
|
|
380
|
+
"..#.#......#.#..",
|
|
381
|
+
"..############..",
|
|
382
|
+
"................",
|
|
383
|
+
"................"
|
|
384
|
+
],
|
|
385
|
+
copy: [
|
|
386
|
+
"................",
|
|
387
|
+
"................",
|
|
388
|
+
"..########......",
|
|
389
|
+
"..#......#......",
|
|
390
|
+
"..#..########...",
|
|
391
|
+
"..#..#......#...",
|
|
392
|
+
"..#..#......#...",
|
|
393
|
+
"..#..#......#...",
|
|
394
|
+
"..#..#......#...",
|
|
395
|
+
"..####......#...",
|
|
396
|
+
".....#......#...",
|
|
397
|
+
".....#......#...",
|
|
398
|
+
".....#......#...",
|
|
399
|
+
".....########...",
|
|
400
|
+
"................",
|
|
401
|
+
"................"
|
|
402
|
+
],
|
|
403
|
+
trash: [
|
|
404
|
+
"................",
|
|
405
|
+
"................",
|
|
406
|
+
"......####......",
|
|
407
|
+
"..############..",
|
|
408
|
+
"..############..",
|
|
409
|
+
"................",
|
|
410
|
+
"...##########...",
|
|
411
|
+
"...#..#..#..#...",
|
|
412
|
+
"...#..#..#..#...",
|
|
413
|
+
"...#..#..#..#...",
|
|
414
|
+
"...#..#..#..#...",
|
|
415
|
+
"...#..#..#..#...",
|
|
416
|
+
"...#........#...",
|
|
417
|
+
"...##########...",
|
|
418
|
+
"................",
|
|
419
|
+
"................"
|
|
420
|
+
],
|
|
421
|
+
grip: [
|
|
422
|
+
"................",
|
|
423
|
+
"................",
|
|
424
|
+
"................",
|
|
425
|
+
".....##..##.....",
|
|
426
|
+
".....##..##.....",
|
|
427
|
+
"................",
|
|
428
|
+
"................",
|
|
429
|
+
".....##..##.....",
|
|
430
|
+
".....##..##.....",
|
|
431
|
+
"................",
|
|
432
|
+
"................",
|
|
433
|
+
".....##..##.....",
|
|
434
|
+
".....##..##.....",
|
|
435
|
+
"................",
|
|
436
|
+
"................",
|
|
437
|
+
"................"
|
|
438
|
+
],
|
|
439
|
+
quick: [
|
|
440
|
+
"................",
|
|
441
|
+
"..........###...",
|
|
442
|
+
".........###....",
|
|
443
|
+
"........###.....",
|
|
444
|
+
".......###......",
|
|
445
|
+
"......###.......",
|
|
446
|
+
".....########...",
|
|
447
|
+
"..........###...",
|
|
448
|
+
".........###....",
|
|
449
|
+
"........###.....",
|
|
450
|
+
".......###......",
|
|
451
|
+
"......##........",
|
|
452
|
+
".....#..........",
|
|
453
|
+
"................",
|
|
454
|
+
"................",
|
|
455
|
+
"................"
|
|
456
|
+
],
|
|
457
|
+
grid: [
|
|
458
|
+
"................",
|
|
459
|
+
"................",
|
|
460
|
+
"..#####..#####..",
|
|
461
|
+
"..#...#..#...#..",
|
|
462
|
+
"..#...#..#...#..",
|
|
463
|
+
"..#...#..#...#..",
|
|
464
|
+
"..#####..#####..",
|
|
465
|
+
"................",
|
|
466
|
+
"................",
|
|
467
|
+
"..#####..#####..",
|
|
468
|
+
"..#...#..#...#..",
|
|
469
|
+
"..#...#..#...#..",
|
|
470
|
+
"..#...#..#...#..",
|
|
471
|
+
"..#####..#####..",
|
|
472
|
+
"................",
|
|
473
|
+
"................"
|
|
474
|
+
],
|
|
475
|
+
menu: [
|
|
476
|
+
"................",
|
|
477
|
+
"................",
|
|
478
|
+
"................",
|
|
479
|
+
"................",
|
|
480
|
+
"................",
|
|
481
|
+
"................",
|
|
482
|
+
"................",
|
|
483
|
+
"..##...##...##..",
|
|
484
|
+
"..##...##...##..",
|
|
485
|
+
"................",
|
|
486
|
+
"................",
|
|
487
|
+
"................",
|
|
488
|
+
"................",
|
|
489
|
+
"................",
|
|
490
|
+
"................",
|
|
491
|
+
"................"
|
|
492
|
+
]
|
|
493
|
+
};
|
|
494
|
+
function N(e) {
|
|
495
|
+
let t = "";
|
|
496
|
+
return e.forEach((e, n) => {
|
|
497
|
+
let r = 0;
|
|
498
|
+
for (; r < e.length;) {
|
|
499
|
+
if (e[r] !== "#") {
|
|
500
|
+
r++;
|
|
501
|
+
continue;
|
|
502
|
+
}
|
|
503
|
+
let i = r;
|
|
504
|
+
for (; e[r] === "#";) r++;
|
|
505
|
+
let a = r - i;
|
|
506
|
+
t += `M${i} ${n}h${a}v1h-${a}z`;
|
|
507
|
+
}
|
|
508
|
+
}), t;
|
|
509
|
+
}
|
|
510
|
+
var P = Object.keys(M), F = Object.fromEntries(P.map((e) => [e, N(M[e])])), I = [
|
|
511
|
+
"role",
|
|
512
|
+
"aria-label",
|
|
513
|
+
"aria-hidden"
|
|
514
|
+
], L = ["d"], R = /* @__PURE__ */ s({
|
|
515
|
+
__name: "FpIcon",
|
|
516
|
+
props: {
|
|
517
|
+
name: {},
|
|
518
|
+
label: {}
|
|
519
|
+
},
|
|
520
|
+
setup(t) {
|
|
521
|
+
let n = t, a = e(() => F[n.name]);
|
|
522
|
+
return (e, t) => (u(), r("svg", {
|
|
523
|
+
viewBox: "0 0 16 16",
|
|
524
|
+
class: "fp-icon",
|
|
525
|
+
role: n.label ? "img" : void 0,
|
|
526
|
+
"aria-label": n.label || void 0,
|
|
527
|
+
"aria-hidden": n.label ? void 0 : "true"
|
|
528
|
+
}, [i("path", { d: a.value }, null, 8, L)], 8, I));
|
|
529
|
+
}
|
|
530
|
+
}), z = /* @__PURE__ */ s({
|
|
531
|
+
__name: "FpLcd",
|
|
532
|
+
props: {
|
|
533
|
+
asChild: { type: Boolean },
|
|
534
|
+
as: { default: "div" }
|
|
535
|
+
},
|
|
536
|
+
setup(e) {
|
|
537
|
+
let n = e;
|
|
538
|
+
return (e, r) => (u(), t(h(x), {
|
|
539
|
+
as: n.as,
|
|
540
|
+
"as-child": n.asChild,
|
|
541
|
+
class: "fp-lcd"
|
|
542
|
+
}, {
|
|
543
|
+
default: b(() => [d(e.$slots, "default")]),
|
|
544
|
+
_: 3
|
|
545
|
+
}, 8, ["as", "as-child"]));
|
|
546
|
+
}
|
|
547
|
+
}), B = {
|
|
548
|
+
key: 0,
|
|
549
|
+
class: "fp-lcd-ghost",
|
|
550
|
+
"aria-hidden": "true"
|
|
551
|
+
}, V = { key: 2 }, H = /* @__PURE__ */ s({
|
|
552
|
+
__name: "FpLcdLine",
|
|
553
|
+
props: {
|
|
554
|
+
text: {},
|
|
555
|
+
ghost: { type: Boolean },
|
|
556
|
+
cells: {},
|
|
557
|
+
redraw: { type: Boolean },
|
|
558
|
+
asChild: { type: Boolean },
|
|
559
|
+
as: { default: "p" }
|
|
560
|
+
},
|
|
561
|
+
setup(i) {
|
|
562
|
+
let a = i, o = e(() => "8".repeat(a.cells ?? a.text.length));
|
|
563
|
+
return (e, i) => (u(), t(h(x), {
|
|
564
|
+
as: a.as,
|
|
565
|
+
"as-child": a.asChild,
|
|
566
|
+
class: "fp-lcd-line"
|
|
567
|
+
}, {
|
|
568
|
+
default: b(() => [a.ghost ? (u(), r("span", B, m(o.value), 1)) : n("", !0), a.redraw ? (u(), r("span", {
|
|
569
|
+
key: a.text,
|
|
570
|
+
class: "fp-lcd-redraw"
|
|
571
|
+
}, m(a.text), 1)) : (u(), r("span", V, m(a.text), 1))]),
|
|
572
|
+
_: 1
|
|
573
|
+
}, 8, ["as", "as-child"]));
|
|
574
|
+
}
|
|
575
|
+
}), U = [
|
|
576
|
+
"role",
|
|
577
|
+
"aria-label",
|
|
578
|
+
"aria-hidden"
|
|
579
|
+
], W = /* @__PURE__ */ s({
|
|
580
|
+
__name: "FpLed",
|
|
581
|
+
props: {
|
|
582
|
+
color: { default: "green" },
|
|
583
|
+
lit: { type: Boolean },
|
|
584
|
+
blink: { type: Boolean },
|
|
585
|
+
label: {}
|
|
586
|
+
},
|
|
587
|
+
setup(e) {
|
|
588
|
+
let t = e, n = {
|
|
589
|
+
green: "fp-led-green",
|
|
590
|
+
amber: "fp-led-amber",
|
|
591
|
+
red: "fp-led-red"
|
|
592
|
+
};
|
|
593
|
+
return (e, i) => (u(), r("span", {
|
|
594
|
+
class: c(["fp-led", [n[t.color], {
|
|
595
|
+
"fp-led-lit": t.lit,
|
|
596
|
+
"fp-blink-twice": t.lit && t.blink
|
|
597
|
+
}]]),
|
|
598
|
+
role: t.label ? "img" : void 0,
|
|
599
|
+
"aria-label": t.label || void 0,
|
|
600
|
+
"aria-hidden": t.label ? void 0 : "true"
|
|
601
|
+
}, null, 10, U));
|
|
602
|
+
}
|
|
603
|
+
}), G = {
|
|
604
|
+
class: "fp-screw",
|
|
605
|
+
"aria-hidden": "true"
|
|
606
|
+
}, K = /* @__PURE__ */ s({
|
|
607
|
+
__name: "FpScrew",
|
|
608
|
+
setup(e) {
|
|
609
|
+
return (e, t) => (u(), r("span", G));
|
|
610
|
+
}
|
|
611
|
+
}), q = /* @__PURE__ */ s({
|
|
612
|
+
__name: "FpSilk",
|
|
613
|
+
props: {
|
|
614
|
+
asChild: { type: Boolean },
|
|
615
|
+
as: { default: "span" }
|
|
616
|
+
},
|
|
617
|
+
setup(e) {
|
|
618
|
+
let n = e;
|
|
619
|
+
return (e, r) => (u(), t(h(x), {
|
|
620
|
+
as: n.as,
|
|
621
|
+
"as-child": n.asChild,
|
|
622
|
+
class: "fp-silk"
|
|
623
|
+
}, {
|
|
624
|
+
default: b(() => [d(e.$slots, "default")]),
|
|
625
|
+
_: 3
|
|
626
|
+
}, 8, ["as", "as-child"]));
|
|
627
|
+
}
|
|
628
|
+
}), J = /* @__PURE__ */ s({
|
|
629
|
+
__name: "FpWell",
|
|
630
|
+
props: {
|
|
631
|
+
asChild: { type: Boolean },
|
|
632
|
+
as: { default: "div" }
|
|
633
|
+
},
|
|
634
|
+
setup(e) {
|
|
635
|
+
let n = e;
|
|
636
|
+
return (e, r) => (u(), t(h(x), {
|
|
637
|
+
as: n.as,
|
|
638
|
+
"as-child": n.asChild,
|
|
639
|
+
class: "fp-well"
|
|
640
|
+
}, {
|
|
641
|
+
default: b(() => [d(e.$slots, "default")]),
|
|
642
|
+
_: 3
|
|
643
|
+
}, 8, ["as", "as-child"]));
|
|
644
|
+
}
|
|
645
|
+
}), Y = ["aria-labelledby"], X = { class: "fp-module-title" }, Z = { class: "fp-window-body" }, Q = /* @__PURE__ */ s({
|
|
646
|
+
__name: "FpWindow",
|
|
647
|
+
props: {
|
|
648
|
+
title: {},
|
|
649
|
+
level: { default: 2 },
|
|
650
|
+
closable: { type: Boolean },
|
|
651
|
+
closeLabel: {},
|
|
652
|
+
sheet: { type: Boolean }
|
|
653
|
+
},
|
|
654
|
+
emits: ["close"],
|
|
655
|
+
setup(e, { emit: s }) {
|
|
656
|
+
let l = e, p = s, _ = g();
|
|
657
|
+
return (e, s) => (u(), r("section", {
|
|
658
|
+
class: c(["fp-window", [l.sheet ? "fp-sheet-panel" : "fp-module"]]),
|
|
659
|
+
"aria-labelledby": h(_)
|
|
660
|
+
}, [i("div", X, [
|
|
661
|
+
(u(), t(f(`h${l.level}`), {
|
|
662
|
+
id: h(_),
|
|
663
|
+
class: "fp-silk fp-window-title"
|
|
664
|
+
}, {
|
|
665
|
+
default: b(() => [a(m(l.title), 1)]),
|
|
666
|
+
_: 1
|
|
667
|
+
}, 8, ["id"])),
|
|
668
|
+
d(e.$slots, "actions"),
|
|
669
|
+
l.closable ? (u(), t(S, {
|
|
670
|
+
key: 0,
|
|
671
|
+
"aria-label": l.closeLabel ?? `Close ${l.title}`,
|
|
672
|
+
onClick: s[0] ||= (e) => p("close")
|
|
673
|
+
}, {
|
|
674
|
+
default: b(() => [o(R, { name: "close" })]),
|
|
675
|
+
_: 1
|
|
676
|
+
}, 8, ["aria-label"])) : n("", !0)
|
|
677
|
+
]), i("div", Z, [d(e.$slots, "default")])], 10, Y));
|
|
678
|
+
}
|
|
679
|
+
});
|
|
680
|
+
//#endregion
|
|
681
|
+
export { S as FpButton, C as FpCap, E as FpDevice, D as FpGelButton, O as FpHousing, R as FpIcon, z as FpLcd, H as FpLcdLine, W as FpLed, K as FpScrew, q as FpSilk, J as FpWell, Q as FpWindow, P as fpIconNames };
|
package/package.json
CHANGED
|
@@ -1,6 +1,57 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@frontpanel/vue",
|
|
3
|
-
"
|
|
4
|
-
"
|
|
5
|
-
"description": "
|
|
3
|
+
"type": "module",
|
|
4
|
+
"version": "0.1.0",
|
|
5
|
+
"description": "Vue 3 components for the Frontpanel early-2000s hardware skin: a scale-to-fit device frame, windows, chrome and gel buttons, caps, LCDs and LEDs, built on Reka UI.",
|
|
6
|
+
"author": "Dulan Katukurundage",
|
|
7
|
+
"license": "MIT",
|
|
8
|
+
"homepage": "https://dulandev.github.io/frontpanel/",
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "git+https://github.com/DulanDev/frontpanel.git",
|
|
12
|
+
"directory": "packages/vue"
|
|
13
|
+
},
|
|
14
|
+
"keywords": [
|
|
15
|
+
"vue",
|
|
16
|
+
"vue3",
|
|
17
|
+
"components",
|
|
18
|
+
"y2k",
|
|
19
|
+
"skeuomorphic",
|
|
20
|
+
"ui-kit",
|
|
21
|
+
"design-system",
|
|
22
|
+
"reka-ui"
|
|
23
|
+
],
|
|
24
|
+
"sideEffects": false,
|
|
25
|
+
"exports": {
|
|
26
|
+
".": {
|
|
27
|
+
"types": "./dist/index.d.ts",
|
|
28
|
+
"import": "./dist/index.js"
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
"files": [
|
|
32
|
+
"dist"
|
|
33
|
+
],
|
|
34
|
+
"peerDependencies": {
|
|
35
|
+
"vue": "^3.5.0"
|
|
36
|
+
},
|
|
37
|
+
"dependencies": {
|
|
38
|
+
"reka-ui": "^2.11.0",
|
|
39
|
+
"@frontpanel/css": "^0.1.0"
|
|
40
|
+
},
|
|
41
|
+
"devDependencies": {
|
|
42
|
+
"@tailwindcss/oxide": "^4.3.3",
|
|
43
|
+
"@vitejs/plugin-vue": "^6.0.8",
|
|
44
|
+
"@vue/test-utils": "^2.5.0",
|
|
45
|
+
"happy-dom": "^20.14.3",
|
|
46
|
+
"tailwindcss": "^4.3.3",
|
|
47
|
+
"vite": "^8.3.0",
|
|
48
|
+
"vue": "^3.5.42",
|
|
49
|
+
"vue-tsc": "^3.3.11"
|
|
50
|
+
},
|
|
51
|
+
"scripts": {
|
|
52
|
+
"build": "vite build && vue-tsc -p tsconfig.build.json",
|
|
53
|
+
"typecheck": "vue-tsc --noEmit",
|
|
54
|
+
"test": "vitest run",
|
|
55
|
+
"test:watch": "vitest"
|
|
56
|
+
}
|
|
6
57
|
}
|