pgo-uiux2 1.0.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/.env +1 -0
- package/.env.production +1 -0
- package/.prettierrc +13 -0
- package/.vscode/extensions.json +3 -0
- package/BUTTON_GUIDE.md +257 -0
- package/README.md +49 -0
- package/THEME_REFERENCE.md +310 -0
- package/eslint.config.ts +27 -0
- package/index.html +13 -0
- package/package.json +85 -0
- package/public/favicon.ico +0 -0
- package/src/App.vue +368 -0
- package/src/assets/fonts/Faruma.ttf +0 -0
- package/src/components/examples/AppBarExample.vue +101 -0
- package/src/components/examples/AvatarExample.vue +47 -0
- package/src/components/examples/BannerExample.vue +287 -0
- package/src/components/examples/BaseInputExample.vue +25 -0
- package/src/components/examples/BreadcrumbExample.vue +53 -0
- package/src/components/examples/CardExample.vue +77 -0
- package/src/components/examples/ChipExample.vue +225 -0
- package/src/components/examples/DatePickerExample.vue +31 -0
- package/src/components/examples/DropdownExample.vue +84 -0
- package/src/components/examples/EditorExample.vue +200 -0
- package/src/components/examples/ExpansionPanelExample.vue +42 -0
- package/src/components/examples/FileUploadExample.vue +40 -0
- package/src/components/examples/FormExample.vue +121 -0
- package/src/components/examples/HugeTest.vue +8 -0
- package/src/components/examples/LayoutContainerExample.vue +80 -0
- package/src/components/examples/ModalExample.vue +82 -0
- package/src/components/examples/NavDrawerExample.vue +170 -0
- package/src/components/examples/NumberFieldExample.vue +145 -0
- package/src/components/examples/RadioButtonExample.vue +161 -0
- package/src/components/examples/SearchExample.vue +322 -0
- package/src/components/examples/SelectExample.vue +121 -0
- package/src/components/examples/StackedTableViewExample.vue +53 -0
- package/src/components/examples/TabExample.vue +336 -0
- package/src/components/examples/TableExample.vue +228 -0
- package/src/components/examples/TextFieldExample.vue +181 -0
- package/src/components/examples/TextareaExample.vue +173 -0
- package/src/components/examples/ThemeToggle.vue +50 -0
- package/src/components/examples/TimelineExample.vue +66 -0
- package/src/components/examples/TipTapEditorExample.vue +20 -0
- package/src/components/examples/TooltipExample.vue +53 -0
- package/src/components/examples/VueDatePickerShowcase.vue +214 -0
- package/src/components/examples/_DatePickerExample.vue +33 -0
- package/src/components/examples/__FormExample.vue +77 -0
- package/src/components/index.ts +25 -0
- package/src/components/pgo/AppBar.vue +347 -0
- package/src/components/pgo/Avatar.vue +139 -0
- package/src/components/pgo/Banner.vue +300 -0
- package/src/components/pgo/Breadcrumb.vue +101 -0
- package/src/components/pgo/Button.vue +171 -0
- package/src/components/pgo/Card.vue +178 -0
- package/src/components/pgo/ConfirmationModel.vue +32 -0
- package/src/components/pgo/DataTable.vue +845 -0
- package/src/components/pgo/DatePicker/CalendarPanel.vue +43 -0
- package/src/components/pgo/DatePicker/__DatePicker.vue +122 -0
- package/src/components/pgo/DatePicker/types.ts +11 -0
- package/src/components/pgo/DatePicker/useCalendar.ts +39 -0
- package/src/components/pgo/DatePicker/useDatePicker.ts +31 -0
- package/src/components/pgo/Deprecated/ToastContainer.vue +51 -0
- package/src/components/pgo/Deprecated/ToastItem.vue +55 -0
- package/src/components/pgo/Dropdown.vue +296 -0
- package/src/components/pgo/DropdownItem.vue +40 -0
- package/src/components/pgo/Editor.vue +511 -0
- package/src/components/pgo/ExpansionPanel.vue +185 -0
- package/src/components/pgo/Footer.vue +39 -0
- package/src/components/pgo/HeroIcon.vue +124 -0
- package/src/components/pgo/InputSearch.vue +194 -0
- package/src/components/pgo/LayoutContainer.vue +104 -0
- package/src/components/pgo/Main.vue +37 -0
- package/src/components/pgo/Modal.vue +273 -0
- package/src/components/pgo/NavDrawer.vue +127 -0
- package/src/components/pgo/NavDrawerItem.vue +161 -0
- package/src/components/pgo/NavigationDrawer.vue +849 -0
- package/src/components/pgo/OLDNavDrawer.vue +661 -0
- package/src/components/pgo/OldAppBar.vue +223 -0
- package/src/components/pgo/PApp.vue +102 -0
- package/src/components/pgo/Pagination.vue +242 -0
- package/src/components/pgo/Search copy.vue +310 -0
- package/src/components/pgo/Search.vue +411 -0
- package/src/components/pgo/StackedTableView.vue +167 -0
- package/src/components/pgo/Tab.vue +617 -0
- package/src/components/pgo/TestInput.vue +395 -0
- package/src/components/pgo/Timeline.vue +367 -0
- package/src/components/pgo/TimelineItem.vue +80 -0
- package/src/components/pgo/TipTapEditor.vue +315 -0
- package/src/components/pgo/Tooltip.NOTES.md +12 -0
- package/src/components/pgo/Tooltip.PROPS.md +21 -0
- package/src/components/pgo/Tooltip.vue +281 -0
- package/src/components/pgo/base/Base.vue +444 -0
- package/src/components/pgo/buttons/Chip.vue +324 -0
- package/src/components/pgo/buttons/ChipGroup.vue +224 -0
- package/src/components/pgo/buttons/Radio.vue +424 -0
- package/src/components/pgo/filters/FilterSection.vue +188 -0
- package/src/components/pgo/filters/Searchbar.vue +216 -0
- package/src/components/pgo/forms/DynamicForm.vue +45 -0
- package/src/components/pgo/forms/Form.vue +132 -0
- package/src/components/pgo/index.ts +15 -0
- package/src/components/pgo/inputs/Checkbox.vue +320 -0
- package/src/components/pgo/inputs/DatePicker.vue +395 -0
- package/src/components/pgo/inputs/FileUpload.vue +326 -0
- package/src/components/pgo/inputs/NumberField.vue +243 -0
- package/src/components/pgo/inputs/Radio.vue +162 -0
- package/src/components/pgo/inputs/RadioGroup.vue +188 -0
- package/src/components/pgo/inputs/Select.vue +535 -0
- package/src/components/pgo/inputs/TextField.vue +194 -0
- package/src/components/pgo/inputs/Textarea.vue +181 -0
- package/src/main.js +12 -0
- package/src/pgo-components/_index.js +31 -0
- package/src/pgo-components/assets/fonts/Faruma.ttf +0 -0
- package/src/pgo-components/assets/fonts/logo.png +0 -0
- package/src/pgo-components/composables/useTheme.js +10 -0
- package/src/pgo-components/directives/tooltip-directive.ts +393 -0
- package/src/pgo-components/index.js +96 -0
- package/src/pgo-components/lib/componentConfig.js +147 -0
- package/src/pgo-components/lib/core/composables/_useCalendar.ts +127 -0
- package/src/pgo-components/lib/core/composables/useDefaults.ts +15 -0
- package/src/pgo-components/lib/core/composables/useLanguageSelect.js +0 -0
- package/src/pgo-components/lib/core/composables/useRtl.ts +12 -0
- package/src/pgo-components/lib/core/defaults/createDefaults.ts +5 -0
- package/src/pgo-components/lib/core/defaults/defaults.ts +7 -0
- package/src/pgo-components/lib/core/rtl/rtl.ts +3 -0
- package/src/pgo-components/lib/core/rtl/setRtl.ts +19 -0
- package/src/pgo-components/lib/drawerState.ts +3 -0
- package/src/pgo-components/lib/i18n/defaultLables.js +71 -0
- package/src/pgo-components/lib/i18n/i18nPlugin.js +52 -0
- package/src/pgo-components/lib/i18n/useI18n.js +35 -0
- package/src/pgo-components/lib/index.ts +38 -0
- package/src/pgo-components/pages/Component.vue +7 -0
- package/src/pgo-components/pages/ComponentRenderer.vue +85 -0
- package/src/pgo-components/pages/Home.vue +130 -0
- package/src/pgo-components/pages/ListView.vue +370 -0
- package/src/pgo-components/pages/Page1.vue +296 -0
- package/src/pgo-components/pages/_Page1.vue +180 -0
- package/src/pgo-components/plugins/SnackBar.vue +251 -0
- package/src/pgo-components/plugins/SnackBarContainer.vue +53 -0
- package/src/pgo-components/plugins/SnackBarPlugin.ts +136 -0
- package/src/pgo-components/plugins/theme-plugin.js +114 -0
- package/src/pgo-components/plugins/types.ts +46 -0
- package/src/pgo-components/plugins/useSnackBar.js +11 -0
- package/src/pgo-components/plugins/useSnackBar.ts +21 -0
- package/src/pgo-components/plugins/validation-plugin.js +11 -0
- package/src/pgo-components/services/Entry.json +813 -0
- package/src/pgo-components/services/axios.js +54 -0
- package/src/pgo-components/services/data.json +90 -0
- package/src/pgo-components/services/person.json +260 -0
- package/src/pgo-components/services/toast.ts +44 -0
- package/src/pgo-components/styles/global.css +234 -0
- package/src/pgo-components/styles/reset.css +96 -0
- package/src/pgo-components/styles/tokens.css +18 -0
- package/src/pgo-components/styles/utilities/border-radius.css +57 -0
- package/src/pgo-components/styles/utilities/borders.css +85 -0
- package/src/pgo-components/styles/utilities/colors.css +38 -0
- package/src/pgo-components/styles/utilities/cursor.css +19 -0
- package/src/pgo-components/styles/utilities/display.css +78 -0
- package/src/pgo-components/styles/utilities/elevation.css +33 -0
- package/src/pgo-components/styles/utilities/flex.css +403 -0
- package/src/pgo-components/styles/utilities/float.css +41 -0
- package/src/pgo-components/styles/utilities/hover.css +9 -0
- package/src/pgo-components/styles/utilities/index.css +18 -0
- package/src/pgo-components/styles/utilities/opacity.css +27 -0
- package/src/pgo-components/styles/utilities/overflow.css +26 -0
- package/src/pgo-components/styles/utilities/palette.css +515 -0
- package/src/pgo-components/styles/utilities/position.css +14 -0
- package/src/pgo-components/styles/utilities/sizing.css +70 -0
- package/src/pgo-components/styles/utilities/spacing.css +578 -0
- package/src/pgo-components/styles/utilities/transitions.css +58 -0
- package/src/pgo-components/styles/utilities/typography.css +91 -0
- package/src/pgo-components/styles/utilities/z-index.css +11 -0
- package/src/pgo-components/tokens/index.js +337 -0
- package/src/router/index.js +88 -0
- package/src/shims-vue.d.ts +14 -0
- package/src/validations/validationRules.js +50 -0
- package/tailwind.config.js +73 -0
- package/test.php +5 -0
- package/tsconfig.json +25 -0
- package/ui +31 -0
- package/ui.pgo.mv.conf +18 -0
- package/vite.config.js +42 -0
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="example-component p-6">
|
|
3
|
+
<h2 class="mb-4 text-lg font-semibold">
|
|
4
|
+
Vue 3 DatePicker Example
|
|
5
|
+
</h2>
|
|
6
|
+
|
|
7
|
+
<DatePicker
|
|
8
|
+
v-model="selectedDate"
|
|
9
|
+
format="yyyy-MM-dd"
|
|
10
|
+
:clearable="true"
|
|
11
|
+
placeholder="Select a date"
|
|
12
|
+
/>
|
|
13
|
+
|
|
14
|
+
<p class="mt-4">
|
|
15
|
+
Selected date: {{ selectedDate ? selectedDate.toDateString() : 'None' }}
|
|
16
|
+
</p>
|
|
17
|
+
</div>
|
|
18
|
+
</template>
|
|
19
|
+
|
|
20
|
+
<script setup lang="ts">
|
|
21
|
+
import { ref } from 'vue'
|
|
22
|
+
import DatePicker from '../pgo/inputs/DatePicker.vue'
|
|
23
|
+
|
|
24
|
+
const selectedDate = ref<Date | null>(null)
|
|
25
|
+
</script>
|
|
26
|
+
|
|
27
|
+
<style scoped>
|
|
28
|
+
.example-component {
|
|
29
|
+
font-family: system-ui, sans-serif;
|
|
30
|
+
}
|
|
31
|
+
</style>
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="p-6 max-w-4xl mx-auto space-y-8">
|
|
3
|
+
<h2 class="text-3xl font-bold text-gray-800 mb-6">Dropdown Components</h2>
|
|
4
|
+
|
|
5
|
+
<Card title="Dropdown Examples" class="space-y-6">
|
|
6
|
+
<div class="flex items-center gap-4 flex-wrap">
|
|
7
|
+
<!-- Basic Dropdown with items prop -->
|
|
8
|
+
<Dropdown label="Select Option" :items="items" @select="handleSelect" />
|
|
9
|
+
<Dropdown variant="outlined" color="success" label="Select Option" :items="items" @select="handleSelect" />
|
|
10
|
+
|
|
11
|
+
<!-- Custom trigger -->
|
|
12
|
+
<Dropdown :items="items" @select="handleSelect">
|
|
13
|
+
<template #trigger>
|
|
14
|
+
<button class="px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700">
|
|
15
|
+
Custom Trigger
|
|
16
|
+
</button>
|
|
17
|
+
</template>
|
|
18
|
+
</Dropdown>
|
|
19
|
+
|
|
20
|
+
<!-- With custom content -->
|
|
21
|
+
<Dropdown label="Actions" align="right">
|
|
22
|
+
<DropdownItem @select="edit">
|
|
23
|
+
<template #prepend>📝</template>
|
|
24
|
+
Edit
|
|
25
|
+
</DropdownItem>
|
|
26
|
+
<DropdownItem @select="view">
|
|
27
|
+
<template #prepend>👁️</template>
|
|
28
|
+
View
|
|
29
|
+
</DropdownItem>
|
|
30
|
+
<div class="border-t my-1"></div>
|
|
31
|
+
<DropdownItem @select="remove">
|
|
32
|
+
<template #prepend>🗑️</template>
|
|
33
|
+
Delete
|
|
34
|
+
</DropdownItem>
|
|
35
|
+
</Dropdown>
|
|
36
|
+
|
|
37
|
+
<!-- Dense variant -->
|
|
38
|
+
<Dropdown label="Dense Menu" dense :items="items" @select="handleSelect" />
|
|
39
|
+
|
|
40
|
+
<!-- Open on hover -->
|
|
41
|
+
<Dropdown label="Hover Menu" open-on-hover :items="items" @select="handleSelect" />
|
|
42
|
+
|
|
43
|
+
<!-- Right aligned -->
|
|
44
|
+
<Dropdown label="Right Aligned" align="right" :items="items" @select="handleSelect" />
|
|
45
|
+
</div>
|
|
46
|
+
|
|
47
|
+
<div class="mt-4 p-4 bg-gray-100 rounded">
|
|
48
|
+
<p class="text-sm font-medium">Selected: {{ selectedItem || 'None' }}</p>
|
|
49
|
+
</div>
|
|
50
|
+
</Card>
|
|
51
|
+
</div>
|
|
52
|
+
</template>
|
|
53
|
+
|
|
54
|
+
<script setup>
|
|
55
|
+
import { ref } from 'vue'
|
|
56
|
+
import Card from '../pgo/Card.vue'
|
|
57
|
+
import Dropdown from '../pgo/Dropdown.vue'
|
|
58
|
+
import DropdownItem from '../pgo/DropdownItem.vue'
|
|
59
|
+
|
|
60
|
+
const selectedItem = ref(null)
|
|
61
|
+
|
|
62
|
+
const items = [
|
|
63
|
+
{ label: 'Profile', value: 'profile' },
|
|
64
|
+
{ label: 'Settings', value: 'settings' },
|
|
65
|
+
{ label: 'Logout', value: 'logout' }
|
|
66
|
+
]
|
|
67
|
+
|
|
68
|
+
const handleSelect = (item) => {
|
|
69
|
+
selectedItem.value = item.label || item
|
|
70
|
+
console.log('Selected:', item)
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const edit = () => {
|
|
74
|
+
console.log('Edit clicked')
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const view = () => {
|
|
78
|
+
console.log('View clicked')
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const remove = () => {
|
|
82
|
+
console.log('Delete clicked')
|
|
83
|
+
}
|
|
84
|
+
</script>
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="space-y-6">
|
|
3
|
+
<!-- Header -->
|
|
4
|
+
<div>
|
|
5
|
+
<h2 class="text-2xl font-bold mb-2">Rich Text Editor Demo</h2>
|
|
6
|
+
<p class="text-gray-600 dark:text-gray-400">A full-featured rich text editor with formatting, tables, and HTML editing</p>
|
|
7
|
+
</div>
|
|
8
|
+
|
|
9
|
+
<!-- Controls Section -->
|
|
10
|
+
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 p-4 bg-gray-50 dark:bg-gray-800 rounded-lg border border-gray-200 dark:border-gray-700">
|
|
11
|
+
<div>
|
|
12
|
+
<label class="block text-sm font-medium mb-2">Character Limit:</label>
|
|
13
|
+
<input
|
|
14
|
+
v-model.number="characterLimit"
|
|
15
|
+
type="number"
|
|
16
|
+
class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded bg-white dark:bg-gray-900"
|
|
17
|
+
min="0"
|
|
18
|
+
placeholder="Leave empty for no limit"
|
|
19
|
+
/>
|
|
20
|
+
</div>
|
|
21
|
+
|
|
22
|
+
<div>
|
|
23
|
+
<label class="flex items-center gap-2 cursor-pointer">
|
|
24
|
+
<input v-model="stickyToolbar" type="checkbox" class="w-4 h-4" />
|
|
25
|
+
<span class="text-sm font-medium">Sticky Toolbar</span>
|
|
26
|
+
</label>
|
|
27
|
+
</div>
|
|
28
|
+
|
|
29
|
+
<div>
|
|
30
|
+
<label class="flex items-center gap-2 cursor-pointer">
|
|
31
|
+
<input v-model="allowHtmlEdit" type="checkbox" class="w-4 h-4" />
|
|
32
|
+
<span class="text-sm font-medium">Allow HTML Editing</span>
|
|
33
|
+
</label>
|
|
34
|
+
</div>
|
|
35
|
+
|
|
36
|
+
<div class="flex gap-2">
|
|
37
|
+
<button
|
|
38
|
+
@click="loadSampleContent"
|
|
39
|
+
class="px-3 py-2 bg-blue-600 hover:bg-blue-700 text-white rounded font-medium transition"
|
|
40
|
+
>
|
|
41
|
+
Load Sample
|
|
42
|
+
</button>
|
|
43
|
+
<button
|
|
44
|
+
@click="clearEditor"
|
|
45
|
+
class="px-3 py-2 bg-red-600 hover:bg-red-700 text-white rounded font-medium transition"
|
|
46
|
+
>
|
|
47
|
+
Clear All
|
|
48
|
+
</button>
|
|
49
|
+
</div>
|
|
50
|
+
</div>
|
|
51
|
+
|
|
52
|
+
<!-- Editor Instance -->
|
|
53
|
+
<div>
|
|
54
|
+
<h3 class="text-lg font-semibold mb-3">Editor</h3>
|
|
55
|
+
<Editor
|
|
56
|
+
v-model="content"
|
|
57
|
+
:maximum-length="characterLimit || null"
|
|
58
|
+
:can-edit-html="allowHtmlEdit"
|
|
59
|
+
:sticky-toolbar="stickyToolbar"
|
|
60
|
+
@limitReached="onLimitReached"
|
|
61
|
+
@limitOk="onLimitOk"
|
|
62
|
+
/>
|
|
63
|
+
</div>
|
|
64
|
+
|
|
65
|
+
<!-- Status and Information -->
|
|
66
|
+
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
67
|
+
<!-- Content Info -->
|
|
68
|
+
<div class="p-4 bg-blue-50 dark:bg-blue-900/30 rounded-lg border border-blue-200 dark:border-blue-800">
|
|
69
|
+
<h4 class="font-semibold mb-2 text-blue-900 dark:text-blue-100">Content Status</h4>
|
|
70
|
+
<div class="space-y-1 text-sm text-blue-800 dark:text-blue-200">
|
|
71
|
+
<p><strong>Characters:</strong> {{ editorCharCount }}</p>
|
|
72
|
+
<p v-if="characterLimit">
|
|
73
|
+
<strong>Limit:</strong> {{ characterLimit }}
|
|
74
|
+
<span v-if="isAtLimit" class="text-red-600 dark:text-red-400 font-medium ml-2">⚠ LIMIT REACHED</span>
|
|
75
|
+
</p>
|
|
76
|
+
<p><strong>Status:</strong> {{ isAtLimit ? '❌ Limit reached' : '✅ Within limit' }}</p>
|
|
77
|
+
</div>
|
|
78
|
+
</div>
|
|
79
|
+
|
|
80
|
+
<!-- Features Info -->
|
|
81
|
+
<div class="p-4 bg-green-50 dark:bg-green-900/30 rounded-lg border border-green-200 dark:border-green-800">
|
|
82
|
+
<h4 class="font-semibold mb-2 text-green-900 dark:text-green-100">Features</h4>
|
|
83
|
+
<ul class="text-sm text-green-800 dark:text-green-200 space-y-1">
|
|
84
|
+
<li>✓ Bold & Underline formatting</li>
|
|
85
|
+
<li>✓ Bullet & Ordered lists</li>
|
|
86
|
+
<li>✓ LTR / RTL direction support</li>
|
|
87
|
+
<li>✓ Table creation & editing</li>
|
|
88
|
+
<li>✓ HTML mode for advanced editing</li>
|
|
89
|
+
<li>✓ Character limit tracking</li>
|
|
90
|
+
</ul>
|
|
91
|
+
</div>
|
|
92
|
+
</div>
|
|
93
|
+
|
|
94
|
+
<!-- Events Log -->
|
|
95
|
+
<div class="p-4 bg-gray-50 dark:bg-gray-800 rounded-lg border border-gray-200 dark:border-gray-700">
|
|
96
|
+
<h4 class="font-semibold mb-2">Recent Events</h4>
|
|
97
|
+
<div class="space-y-1 text-sm max-h-32 overflow-y-auto">
|
|
98
|
+
<div v-if="eventLog.length === 0" class="text-gray-500 dark:text-gray-400">
|
|
99
|
+
No events yet
|
|
100
|
+
</div>
|
|
101
|
+
<div v-for="(event, idx) in eventLog.slice(-5)" :key="idx" class="text-gray-700 dark:text-gray-300">
|
|
102
|
+
<span class="text-xs text-gray-500 dark:text-gray-500">{{ event.time }}</span>
|
|
103
|
+
{{ event.message }}
|
|
104
|
+
</div>
|
|
105
|
+
</div>
|
|
106
|
+
</div>
|
|
107
|
+
|
|
108
|
+
<!-- HTML Output -->
|
|
109
|
+
<div class="p-4 bg-gray-50 dark:bg-gray-800 rounded-lg border border-gray-200 dark:border-gray-700">
|
|
110
|
+
<h4 class="font-semibold mb-2">HTML Output</h4>
|
|
111
|
+
<div class="p-3 bg-white dark:bg-gray-900 rounded border border-gray-300 dark:border-gray-600 font-mono text-xs overflow-x-auto max-h-40 overflow-y-auto">
|
|
112
|
+
<code>{{ content }}</code>
|
|
113
|
+
</div>
|
|
114
|
+
</div>
|
|
115
|
+
</div>
|
|
116
|
+
</template>
|
|
117
|
+
|
|
118
|
+
<script setup lang="ts">
|
|
119
|
+
import { ref, watch } from 'vue'
|
|
120
|
+
import Editor from '../pgo/Editor.vue'
|
|
121
|
+
|
|
122
|
+
const content = ref('<p>Hello world</p>')
|
|
123
|
+
const characterLimit = ref(500)
|
|
124
|
+
const allowHtmlEdit = ref(true)
|
|
125
|
+
const stickyToolbar = ref(true)
|
|
126
|
+
const editorCharCount = ref(0)
|
|
127
|
+
const isAtLimit = ref(false)
|
|
128
|
+
const eventLog = ref<Array<{ time: string; message: string }>>([])
|
|
129
|
+
|
|
130
|
+
const sampleContent = `
|
|
131
|
+
<h2>Welcome to the Rich Text Editor</h2>
|
|
132
|
+
<p>This editor supports the following formatting options:</p>
|
|
133
|
+
<ul>
|
|
134
|
+
<li><strong>Bold text</strong> for emphasis</li>
|
|
135
|
+
<li><u>Underlined text</u> for additional highlighting</li>
|
|
136
|
+
<li>Bullet lists for organizing information</li>
|
|
137
|
+
</ul>
|
|
138
|
+
<ol>
|
|
139
|
+
<li>Numbered lists for sequential items</li>
|
|
140
|
+
<li>Perfect for instructions or steps</li>
|
|
141
|
+
</ol>
|
|
142
|
+
<p>You can also:</p>
|
|
143
|
+
<ul>
|
|
144
|
+
<li>Insert tables for structured data</li>
|
|
145
|
+
<li>Edit HTML directly when needed</li>
|
|
146
|
+
<li>Use LTR or RTL text direction</li>
|
|
147
|
+
<li>Track character count with limits</li>
|
|
148
|
+
</ul>
|
|
149
|
+
`
|
|
150
|
+
|
|
151
|
+
function loadSampleContent() {
|
|
152
|
+
content.value = sampleContent.replace(/\n\s+/g, '').trim()
|
|
153
|
+
addEvent('Sample content loaded')
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
function clearEditor() {
|
|
157
|
+
if (confirm('Are you sure you want to clear all content?')) {
|
|
158
|
+
content.value = '<p></p>'
|
|
159
|
+
addEvent('Editor cleared')
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
function onLimitReached() {
|
|
164
|
+
isAtLimit.value = true
|
|
165
|
+
addEvent('⚠️ Character limit reached! Editing disabled.')
|
|
166
|
+
console.warn('Character limit reached')
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
function onLimitOk() {
|
|
170
|
+
isAtLimit.value = false
|
|
171
|
+
addEvent('✅ Back under character limit')
|
|
172
|
+
console.log('Back under limit')
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
function addEvent(message: string) {
|
|
176
|
+
const now = new Date()
|
|
177
|
+
const time = now.toLocaleTimeString('en-US', {
|
|
178
|
+
hour: '2-digit',
|
|
179
|
+
minute: '2-digit',
|
|
180
|
+
second: '2-digit'
|
|
181
|
+
})
|
|
182
|
+
eventLog.value.push({ time, message })
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// Watch for content changes to update character count
|
|
186
|
+
const updateCharCount = () => {
|
|
187
|
+
// Count only visible text characters
|
|
188
|
+
const div = document.createElement('div')
|
|
189
|
+
div.innerHTML = content.value
|
|
190
|
+
editorCharCount.value = div.innerText.length
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// Update character count when content changes
|
|
194
|
+
watch(content, () => {
|
|
195
|
+
updateCharCount()
|
|
196
|
+
})
|
|
197
|
+
|
|
198
|
+
// Initial character count
|
|
199
|
+
updateCharCount()
|
|
200
|
+
</script>
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div>
|
|
3
|
+
<ExpansionPanel :panelsData="panels" :allowMultiple="false" :readOnly="false" :disable="false" />
|
|
4
|
+
</div>
|
|
5
|
+
</template>
|
|
6
|
+
|
|
7
|
+
<script>
|
|
8
|
+
import ExpansionPanel from '../pgo/ExpansionPanel.vue';
|
|
9
|
+
|
|
10
|
+
export default {
|
|
11
|
+
components: {
|
|
12
|
+
ExpansionPanel
|
|
13
|
+
},
|
|
14
|
+
data() {
|
|
15
|
+
return {
|
|
16
|
+
panels: [
|
|
17
|
+
{
|
|
18
|
+
title: 'Panel 1',
|
|
19
|
+
content: 'This is the content of Panel 1.',
|
|
20
|
+
icon: '🔒',
|
|
21
|
+
readonly: false,
|
|
22
|
+
disabled: false
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
title: 'Panel 2',
|
|
26
|
+
content: 'This is the content of Panel 2.',
|
|
27
|
+
icon: '✅',
|
|
28
|
+
readonly: false,
|
|
29
|
+
disabled: false
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
title: 'Panel 3',
|
|
33
|
+
content: 'This is the content of Panel 3.',
|
|
34
|
+
icon: '📚',
|
|
35
|
+
readonly: true,
|
|
36
|
+
disabled: false
|
|
37
|
+
}
|
|
38
|
+
]
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
</script>
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<Card :title="'File Upload'" class="mb-4">
|
|
3
|
+
<div class="space-y-3">
|
|
4
|
+
<FileUpload
|
|
5
|
+
v-model="files"
|
|
6
|
+
label="Upload files"
|
|
7
|
+
hint="Images allowed, max 2MB each"
|
|
8
|
+
:accept="'image/*,.pdf'"
|
|
9
|
+
:max-size-mb="2"
|
|
10
|
+
:multiple="true"
|
|
11
|
+
|
|
12
|
+
/>
|
|
13
|
+
|
|
14
|
+
<div v-if="files.length" class="mt-2">
|
|
15
|
+
<div class="text-sm text-input-text mb-1">Selected:</div>
|
|
16
|
+
<ul class="space-y-1">
|
|
17
|
+
<li v-for="(f, i) in files" :key="i" class="text-xs text-input-text">{{ f.file.name }} — {{ formatSize(f.file.size) }}</li>
|
|
18
|
+
</ul>
|
|
19
|
+
</div>
|
|
20
|
+
</div>
|
|
21
|
+
</Card>
|
|
22
|
+
</template>
|
|
23
|
+
|
|
24
|
+
<script setup>
|
|
25
|
+
import { ref } from 'vue'
|
|
26
|
+
import Card from '../pgo/Card.vue'
|
|
27
|
+
import FileUpload from '../pgo/inputs/FileUpload.vue'
|
|
28
|
+
|
|
29
|
+
const files = ref([])
|
|
30
|
+
|
|
31
|
+
function formatSize(bytes) {
|
|
32
|
+
if (bytes < 1024) return `${bytes} B`
|
|
33
|
+
const kb = bytes / 1024
|
|
34
|
+
if (kb < 1024) return `${kb.toFixed(1)} KB`
|
|
35
|
+
const mb = kb / 1024
|
|
36
|
+
return `${mb.toFixed(2)} MB`
|
|
37
|
+
}
|
|
38
|
+
</script>
|
|
39
|
+
|
|
40
|
+
<style scoped></style>
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<Card
|
|
3
|
+
:title="'Form Example'"
|
|
4
|
+
class="mb-4"
|
|
5
|
+
bg=""
|
|
6
|
+
>
|
|
7
|
+
<!-- Debug Info -->
|
|
8
|
+
<div class="mb-4 p-4 bg-surface rounded">
|
|
9
|
+
<div>Form Valid: {{ isValid }}</div>
|
|
10
|
+
<div>Form Data: {{ data }}</div>
|
|
11
|
+
</div>
|
|
12
|
+
|
|
13
|
+
<!-- New Vuetify-style Form -->
|
|
14
|
+
<Form
|
|
15
|
+
ref="form"
|
|
16
|
+
v-model="isValid"
|
|
17
|
+
validate-on="blur"
|
|
18
|
+
padding="p-4 space-y-4"
|
|
19
|
+
>
|
|
20
|
+
<div class="space-y-4">
|
|
21
|
+
<InputSearch
|
|
22
|
+
v-model="data.name"
|
|
23
|
+
label="Name"
|
|
24
|
+
:rules="[rules.required, rules.min(3)]"
|
|
25
|
+
/>
|
|
26
|
+
|
|
27
|
+
<Select
|
|
28
|
+
v-model="data.country"
|
|
29
|
+
label="Country"
|
|
30
|
+
:items="countries"
|
|
31
|
+
item-title="text"
|
|
32
|
+
item-value="value"
|
|
33
|
+
:rules="[rules.required]"
|
|
34
|
+
:searchable="true"
|
|
35
|
+
:multiple="true"
|
|
36
|
+
/>
|
|
37
|
+
|
|
38
|
+
<InputSearch
|
|
39
|
+
v-model="data.nid"
|
|
40
|
+
label="NID"
|
|
41
|
+
:rules="[rules.required, rules.customPattern(
|
|
42
|
+
() => data.country === 'mv',
|
|
43
|
+
'^A\\d{6}$',
|
|
44
|
+
'NID must start with A followed by 6 digits for Maldives'
|
|
45
|
+
)]"
|
|
46
|
+
/>
|
|
47
|
+
<TextField
|
|
48
|
+
v-model="data.nid2"
|
|
49
|
+
label="NID2"
|
|
50
|
+
:rules="[rules.required, rules.nid(data.country)]"
|
|
51
|
+
/>
|
|
52
|
+
<Textarea
|
|
53
|
+
v-model="data.description"
|
|
54
|
+
label="Description"
|
|
55
|
+
:rules="[rules.max(200)]"
|
|
56
|
+
/>
|
|
57
|
+
|
|
58
|
+
<div class="flex gap-2">
|
|
59
|
+
<Button
|
|
60
|
+
type="submit"
|
|
61
|
+
:disabled="!isValid"
|
|
62
|
+
@click="submit"
|
|
63
|
+
>
|
|
64
|
+
Submit
|
|
65
|
+
</Button>
|
|
66
|
+
|
|
67
|
+
<Button
|
|
68
|
+
@click="form?.reset()"
|
|
69
|
+
label="reset"
|
|
70
|
+
/>
|
|
71
|
+
|
|
72
|
+
<!-- <Button
|
|
73
|
+
@click="form?.validate()"
|
|
74
|
+
variant="outlined"
|
|
75
|
+
>
|
|
76
|
+
Validate
|
|
77
|
+
</Button> -->
|
|
78
|
+
</div>
|
|
79
|
+
</div>
|
|
80
|
+
</Form>
|
|
81
|
+
</Card>
|
|
82
|
+
</template>
|
|
83
|
+
|
|
84
|
+
<script setup>
|
|
85
|
+
import { ref, inject } from 'vue'
|
|
86
|
+
import Card from '../pgo/Card.vue'
|
|
87
|
+
import Form from '../pgo/forms/Form.vue'
|
|
88
|
+
import InputSearch from '../pgo/InputSearch.vue'
|
|
89
|
+
import TextField from '../pgo/inputs/TextField.vue'
|
|
90
|
+
import Select from '../pgo/inputs/Select.vue'
|
|
91
|
+
import Button from '../pgo/Button.vue'
|
|
92
|
+
import Textarea from '../pgo/inputs/Textarea.vue'
|
|
93
|
+
// import rules from '../validations/validationRules'
|
|
94
|
+
|
|
95
|
+
const rules = inject('validationRules')
|
|
96
|
+
|
|
97
|
+
const form = ref(null)
|
|
98
|
+
const isValid = ref(false) // Track form validity
|
|
99
|
+
|
|
100
|
+
const data = ref({
|
|
101
|
+
name: '',
|
|
102
|
+
role: '',
|
|
103
|
+
country: [],
|
|
104
|
+
nid: '',
|
|
105
|
+
nid2: '',
|
|
106
|
+
description: '',
|
|
107
|
+
})
|
|
108
|
+
|
|
109
|
+
const countries = [
|
|
110
|
+
{ text: 'Maldives', value: 'mv' },
|
|
111
|
+
{ text: 'India', value: 'in' },
|
|
112
|
+
{ text: 'Sri Lanka', value: 'lk' },
|
|
113
|
+
]
|
|
114
|
+
|
|
115
|
+
const submit = async () => {
|
|
116
|
+
const { valid } = await form.value.validate()
|
|
117
|
+
if (!valid) return
|
|
118
|
+
|
|
119
|
+
console.log('FORM OK', data.value)
|
|
120
|
+
}
|
|
121
|
+
</script>
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<LayoutContainer>
|
|
3
|
+
<!-- Default slot → Main Content -->
|
|
4
|
+
<template #default>
|
|
5
|
+
<div>
|
|
6
|
+
<h1 class="text-3xl font-bold mb-4">Dashboard</h1>
|
|
7
|
+
|
|
8
|
+
<p class="text-gray-600 mb-6">This is the main content area.</p>
|
|
9
|
+
|
|
10
|
+
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
|
11
|
+
<div v-for="n in 9" :key="n" class="bg-white p-4 rounded shadow">
|
|
12
|
+
<h2 class="font-semibold mb-2">Card {{ n }}</h2>
|
|
13
|
+
<p class="text-sm text-gray-500">
|
|
14
|
+
Example content for card number {{ n }}.
|
|
15
|
+
</p>
|
|
16
|
+
</div>
|
|
17
|
+
</div>
|
|
18
|
+
</div>
|
|
19
|
+
|
|
20
|
+
<div class="flex-1">
|
|
21
|
+
<NavDrawerExample />
|
|
22
|
+
<AppBarExample />
|
|
23
|
+
</div>
|
|
24
|
+
|
|
25
|
+
<div class="container mx-auto p-6">
|
|
26
|
+
<!-- Stacked Table View Example -->
|
|
27
|
+
<StackedTableViewExample />
|
|
28
|
+
|
|
29
|
+
<!-- TextField Example -->
|
|
30
|
+
<TextFieldExample />
|
|
31
|
+
|
|
32
|
+
<!-- Textarea Example -->
|
|
33
|
+
<TextareaExample />
|
|
34
|
+
|
|
35
|
+
<!-- Dropdown Examples -->
|
|
36
|
+
<DropdownExample />
|
|
37
|
+
|
|
38
|
+
<!-- Card Example -->
|
|
39
|
+
<CardExample />
|
|
40
|
+
|
|
41
|
+
<!-- Chips Examples -->
|
|
42
|
+
<ChipExample />
|
|
43
|
+
|
|
44
|
+
<!-- DataTable Example -->
|
|
45
|
+
<TableExample />
|
|
46
|
+
|
|
47
|
+
<!-- Select Example -->
|
|
48
|
+
<!-- <SelectExample /> -->
|
|
49
|
+
|
|
50
|
+
<!-- Banner Example -->
|
|
51
|
+
<BannerExample />
|
|
52
|
+
|
|
53
|
+
<!-- Search Example -->
|
|
54
|
+
<SearchExample />
|
|
55
|
+
</div>
|
|
56
|
+
</template>
|
|
57
|
+
|
|
58
|
+
<!-- Footer slot -->
|
|
59
|
+
<template #footer>
|
|
60
|
+
<div class="text-center text-gray-500 text-sm">© 2025 My Awesome App</div>
|
|
61
|
+
</template>
|
|
62
|
+
</LayoutContainer>
|
|
63
|
+
</template>
|
|
64
|
+
|
|
65
|
+
<script setup lang="ts">
|
|
66
|
+
import AppBarExample from "../examples/AppBarExample.vue";
|
|
67
|
+
import NavDrawerExample from "../examples/NavDrawerExample.vue";
|
|
68
|
+
import ChipExample from "../examples/ChipExample.vue";
|
|
69
|
+
import TableExample from "../examples/TableExample.vue";
|
|
70
|
+
import SelectExample from "../examples/SelectExample.vue";
|
|
71
|
+
import CardExample from "../examples/CardExample.vue";
|
|
72
|
+
import DropdownExample from "../examples/DropdownExample.vue";
|
|
73
|
+
import TextareaExample from "../examples/TextareaExample.vue";
|
|
74
|
+
import TextFieldExample from "../examples/TextFieldExample.vue";
|
|
75
|
+
import BannerExample from "../examples/BannerExample.vue";
|
|
76
|
+
import SearchExample from "../examples/SearchExample.vue";
|
|
77
|
+
import StackedTableViewExample from "../examples/StackedTableViewExample.vue";
|
|
78
|
+
|
|
79
|
+
import LayoutContainer from "../pgo/LayoutContainer.vue";
|
|
80
|
+
</script>
|