Newer
Older
gnexus-ui-kit / demo / vue.html
@Eugene Sukhodolskiy Eugene Sukhodolskiy 9 hours ago 18 KB Add GnRepeater component for dynamic field groups
<!DOCTYPE html>
<html lang="ru">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>GNexus UI Kit — Vue Adapter Demo</title>
  <link rel="stylesheet" href="/assets/fonts/phosphor-icons/src/css/icons.css">
  <link rel="stylesheet" href="/assets/libs/highlight/styles/base16/summerfruit-dark.min.css">
  <link rel="stylesheet" href="/css/kit.css">
  <link rel="stylesheet" href="/css/demo.css">
  <style>
    body {
      margin: 0;
      background: #16161E;
      color: #C0CAF5;
      font-family: "IBM Plex Mono", "Courier New", monospace;
    }
  </style>
  <script type="importmap">
  {
    "imports": {
      "vue": "https://unpkg.com/vue@3.5.13/dist/vue.esm-browser.js",
      "gnexus-ui-kit/vue": "/vue/index.js"
    }
  }
  </script>
</head>
<body>
  <div id="app"></div>

  <script type="module">
    import { createApp, ref, onMounted } from "vue";
    import {
      GnButton, GnIconButton, GnCopyButton,
      GnBadge, GnAlert,
      GnInput, GnSelect, GnTextarea, GnCheckbox, GnSwitch, GnRadioGroup, GnRange, GnCombobox, GnFileUpload,
      GnTabs, GnTable, GnCard, GnHorizontalCard, GnLoginCard, GnMetricCard, GnStatusCard, GnActionCard, GnUserCard,
      GnModal, GnDrawer, GnConfirmDialog, GnPopover, GnTooltip, GnDropdown,
      GnNavList, GnSteps, GnProgress, GnProgressStages, GnTimeline, GnActivityLog,
      GnDescriptionList, GnUsageMeter, GnEmptyState, GnSkeleton,
      GnAvatar, GnIdentity, GnAvatarStack,
      GnList, GnActionList, GnDefinitionList,
      GnChip, GnChipGroup,
      GnSearchField, GnPagination, GnToolbar,
      GnPageHeader, GnToastProvider,
      GnAccordion, GnNavigationShell, GnInputGroup, GnTagInput, GnRepeater
    } from "gnexus-ui-kit/vue";

    createApp({
      components: {
        GnButton, GnIconButton, GnCopyButton,
        GnBadge, GnAlert,
        GnInput, GnSelect, GnTextarea, GnCheckbox, GnSwitch, GnRadioGroup, GnRange, GnCombobox, GnFileUpload,
        GnTabs, GnTable, GnCard, GnHorizontalCard, GnLoginCard, GnMetricCard, GnStatusCard, GnActionCard, GnUserCard,
        GnModal, GnDrawer, GnConfirmDialog, GnPopover, GnTooltip, GnDropdown,
        GnNavList, GnSteps, GnProgress, GnProgressStages, GnTimeline, GnActivityLog,
        GnDescriptionList, GnUsageMeter, GnEmptyState, GnSkeleton,
        GnAvatar, GnIdentity, GnAvatarStack,
        GnList, GnActionList, GnDefinitionList,
        GnChip, GnChipGroup,
        GnSearchField, GnPagination, GnToolbar,
        GnPageHeader, GnToastProvider,
        GnAccordion, GnNavigationShell, GnInputGroup, GnTagInput, GnRepeater
      },
      setup() {
        const toastRef = ref(null);
        const showToast = (type, options) => toastRef.value?.[type](options);
        const modalOpen = ref(false);
        const drawerOpen = ref(false);
        const confirmOpen = ref(false);
        const name = ref("");
        const status = ref("active");
        const tab = ref("overview");
        const tabCompact = ref("api");
        const tabVertical = ref("profile");
        const accordionOpen = ref("release-checklist");
        const checked = ref(true);
        const switched = ref(false);
        const mode = ref("auto");
        const rollout = ref(64);
        const assignee = ref("");
        const numberValue = ref(42);
        const files = ref([]);
        const searchQuery = ref("");
        const searchValue = ref("release");
        const checkedDisabled = ref(true);
        const currentPage = ref(1);
        const leftDrawerOpen = ref(false);
        const demoTags = ref(["frontend", "vue"]);
        const demoRepeater = ref([
          { id: 1, name: "username", value: "" },
          { id: 2, name: "password", value: "" }
        ]);
        const currentSection = ref("Typography");

        onMounted(() => {
          const observer = new IntersectionObserver((entries) => {
            for (const entry of entries) {
              if (entry.isIntersecting) {
                const id = entry.target.id;
                const item = navItemsVue.find(i => i.href === `#${id}`);
                if (item) currentSection.value = item.label;
              }
            }
          }, { rootMargin: "-58px 0px -80% 0px", threshold: 0 });
          document.querySelectorAll(".docs-section").forEach(el => observer.observe(el));

          setTimeout(() => {
            const container = document.querySelector(".advanced-select-container");
            const input = document.querySelector(".advanced-select-input");
            if (container && input && typeof advancedSelect !== "undefined") {
              container.append(advancedSelect(
                input,
                {
                  "name_1": "Joe",
                  "name_2": "James",
                  "name_3": "Jack",
                  "name_4": "Eliza",
                  "name_5": "Emily",
                  "name_6": "Eleanor",
                  "name_7": "Ella",
                  "name_8": "Ellie",
                  "name_9": "John",
                  "name_10": "David"
                },
                "Nothing found"
              ));
            }
          }, 300);
        });

        const statusOptions = [
          { value: "active", label: "Active" },
          { value: "paused", label: "Paused" },
          { value: "archived", label: "Archived" }
        ];
        const tabs = [
          { id: "overview", label: "Overview", icon: "ph-chart-bar" },
          { id: "activity", label: "Activity", icon: "ph-clock" },
          { id: "settings", label: "Settings", icon: "ph-sliders" }
        ];
        const tabsCompact = [
          { id: "api", label: "API" },
          { id: "webhooks", label: "Webhooks" },
          { id: "billing", label: "Billing", disabled: true }
        ];
        const tabsVertical = [
          { id: "profile", label: "Profile" },
          { id: "access", label: "Access" },
          { id: "notes", label: "Notes" }
        ];
        const tableColumns = [
          { key: "project", label: "Project" },
          { key: "status", label: "Status" },
          { key: "owner", label: "Owner" },
          { key: "updated", label: "Updated" },
          { key: "actions", label: "Actions" }
        ];
        const tableRows = [
          { project: "Website Redesign", status: "Online", owner: "@design", updated: "2 min ago" },
          { project: "Billing API", status: "Degraded", owner: "@backend", updated: "1 hour ago" },
          { project: "Archive Import", status: "Offline", owner: "@ops", updated: "Yesterday" }
        ];
        const modes = [
          { label: "Auto", value: "auto" },
          { label: "Manual", value: "manual" },
          { label: "Locked", value: "locked", disabled: true }
        ];
        const people = [
          { label: "Joe", value: "joe" },
          { label: "James", value: "james" },
          { label: "Jack", value: "jack" },
          { label: "Eliza", value: "eliza" },
          { label: "Emily", value: "emily" },
          { label: "Eleanor", value: "eleanor" },
          { label: "Ella", value: "ella" },
          { label: "Ellie", value: "ellie" },
          { label: "John", value: "john" },
          { label: "David", value: "david" }
        ];
        const steps = [
          { title: "Account", status: "complete", text: "Basic profile data is ready." },
          { title: "Plan", status: "complete", text: "Billing plan is selected." },
          { title: "Confirm", status: "current", text: "Review settings before launch." },
          { title: "Launch", text: "Available after confirmation." }
        ];
        const stepsVertical = [
          { title: "Queued", status: "complete", text: "Job accepted and waiting for worker slot." },
          { title: "Running", status: "current", text: "Current task is processing input data." },
          { title: "Report", text: "Final summary appears after completion." }
        ];
        const stages = [
          { label: "Queued", status: "complete" },
          { label: "Build", status: "complete" },
          { label: "Deploy", status: "current" },
          { label: "Verify" }
        ];
        const details = [
          { key: "project", term: "Project", value: "Website Redesign" },
          { key: "status", term: "Status" },
          { key: "owner", term: "Owner" },
          { key: "updated", term: "Updated", value: "2026-04-11 22:12" }
        ];
        const activity = [
          { key: "created", time: "22:24", title: "Build completed", variant: "success" },
          { key: "synced", time: "22:18", title: "Review requested", variant: "warning" },
          { key: "commit", time: "22:10", title: "Commit pushed", variant: "secondary" }
        ];
        const timeline = [
          { time: "22:24", title: "Build completed", variant: "success", icon: "ph-check-circle", text: "Production bundle finished without warnings.", meta: [
            { label: "Done", variant: "success" },
            { label: "CI" }
          ]},
          { time: "22:18", title: "Review requested", variant: "warning", icon: "ph-warning", text: "Design tokens changed and need one visual pass before release.", meta: [
            { label: "Review", variant: "warning" }
          ]},
          { time: "22:10", title: "Commit pushed", icon: "ph-git-commit", text: "Component documentation and demo examples were updated." }
        ];
        const navItems = [
          { label: "Overview", icon: "ph-house", href: "#" },
          { label: "Records", icon: "ph-table", href: "#" },
          { label: "Settings", icon: "ph-gear", href: "#" }
        ];
        const navListItems = [
          { label: "Overview", active: true, href: "#" },
          { label: "Projects", icon: "ph-stack", meta: "12", href: "#" },
          { label: "Logs", href: "#" },
          { label: "Advanced", disabled: true, href: "#" }
        ];
        const navItemsVue = [
          { label: "Typography", icon: "ph-text-aa", href: "#typography" },
          { label: "Palette", icon: "ph-palette", href: "#colors" },
          { label: "Buttons", icon: "ph-hand-pointing", href: "#buttons" },
          { label: "Forms", icon: "ph-textbox", href: "#forms" },
          { label: "Utilities", icon: "ph-ruler", href: "#utilities" },
          { label: "Editable String", icon: "ph-pencil-simple", href: "#editable-string" },
          { label: "Navigation & Overlays", icon: "ph-stack", href: "#navigation-overlays" },
          { label: "Navigation Shell", icon: "ph-sidebar-simple", href: "#navigation-shell" },
          { label: "Lists", icon: "ph-list-bullets", href: "#lists" },
          { label: "Badges", icon: "ph-tag", href: "#badges" },
          { label: "Alerts", icon: "ph-warning", href: "#alerts" },
          { label: "Tables", icon: "ph-table", href: "#tables" },
          { label: "Data Patterns", icon: "ph-chart-bar", href: "#data-patterns" },
          { label: "Page Header", icon: "ph-browser", href: "#page-header" },
          { label: "Key-Value", icon: "ph-list-dashes", href: "#description-list" },
          { label: "Progress", icon: "ph-activity", href: "#progress" },
          { label: "Steps", icon: "ph-list-numbers", href: "#steps" },
          { label: "Chips", icon: "ph-tag", href: "#chips" },
          { label: "Avatar", icon: "ph-user-circle", href: "#avatar" },
          { label: "Timeline", icon: "ph-clock", href: "#timeline" },
          { label: "Accordion", icon: "ph-caret-down", href: "#accordion" },
          { label: "Tabs", icon: "ph-tabs", href: "#tabs" },
          { label: "Drawer", icon: "ph-sidebar", href: "#drawer" },
          { label: "Toasts", icon: "ph-notification", href: "#toasts" },
          { label: "Cards", icon: "ph-squares-four", href: "#cards" },
          { label: "Modals", icon: "ph-browser", href: "#modals" },
          { label: "Confirm Dialog", icon: "ph-warning", href: "#confirm-dialog" }
        ];
        const accordionItems = [
          { id: "release-checklist", label: "Release checklist", icon: "ph-list-checks", content: "Check component states, copy examples, keyboard focus, and responsive layout before release." },
          { id: "documentation-notes", label: "Documentation notes", icon: "ph-article", content: "Keep component copy short and include code examples for the smallest useful markup." },
          { id: "runtime-behavior", label: "Runtime behavior", icon: "ph-activity", content: "Use native disclosure behavior when the component does not need custom animation or async content." }
        ];
        const listItems = [
          { label: "Dashboard" },
          { label: "Projects" },
          { label: "Reports" },
          { label: "Automations" },
          { label: "Settings" }
        ];
        const actionListItems = [
          { title: "Release Plan", status: "success", ip: "192.168.2.21", btn1: "Open", btn2: "Toggle", btn2Variant: "accent" },
          { title: "Analytics Sync", status: "success", ip: "192.168.2.34", btn1: "Open", btn2: "Restart", btn2Variant: "danger", btn2Icon: "ph-arrow-clockwise" },
          { title: "Archive Job", muted: true, status: "warning", ip: "Offline", btn1: "Open", btn1Disabled: true, btn2: "Toggle", btn2Variant: "accent", btn2Disabled: true }
        ];
        const definitionItems = [
          { term: "Item", description: "Базовая сущность интерфейса" },
          { term: "Group", description: "Логическая группа элементов" },
          { term: "Flow", description: "Набор действий, выполняемых последовательно" }
        ];
        const dropdownItems = [
          { label: "Edit", icon: "ph-pencil-simple" },
          { label: "Duplicate", icon: "ph-copy" },
          { label: "Delete", icon: "ph-trash", danger: true }
        ];

        function save() {
          showToast('success', { title: "Saved", text: name.value || "Changes applied" });
          modalOpen.value = false;
        }

        function confirmAction() {
          showToast('success', { title: "Confirmed", text: "Action was confirmed" });
          confirmOpen.value = false;
        }

        return {
          modalOpen, drawerOpen, confirmOpen, leftDrawerOpen,
          name, status, tab, tabCompact, tabVertical, accordionOpen, checked, checkedDisabled, switched, mode, rollout, assignee, files, searchQuery, searchValue, numberValue, currentPage, currentSection, demoTags, demoRepeater,
          statusOptions, tabs, tabsCompact, tabsVertical, tableColumns, tableRows, modes, people, steps, stepsVertical, stages,
          details, activity, timeline, navItems, navItemsVue, navListItems, listItems, actionListItems, definitionItems, accordionItems, dropdownItems,
          save, confirmAction, showToast, toastRef
        };
      },
      template: `
        <GnToastProvider ref="toastRef">
          <GnNavigationShell :items="navItemsVue" brand="GNexus UI Kit" title="Sections" subtitle="Component library" :current="currentSection">
            <template #content>
              <main class="container docs-page">
                <header class="section docs-intro">
                  <h1 class="contrast">GNexus UI Kit</h1>
                  <p>Набор базовых элементов интерфейса.</p>
                </header>

                <div class="docs-layout">
                  <div class="docs-content">
@@include("partials/vue/typography.html")
@@include("partials/vue/palette.html")
@@include("partials/vue/buttons.html")
@@include("partials/vue/forms.html")
@@include("partials/vue/utilities.html")
@@include("partials/vue/editable-string.html")
@@include("partials/vue/navigation-overlays.html")
@@include("partials/vue/navigation-shell.html")
@@include("partials/vue/lists.html")
@@include("partials/vue/badges.html")
@@include("partials/vue/alerts.html")
@@include("partials/vue/tables.html")
@@include("partials/vue/data-patterns.html")
@@include("partials/vue/page-header.html")
@@include("partials/vue/description-list.html")
@@include("partials/vue/progress.html")
@@include("partials/vue/steps.html")
@@include("partials/vue/chips.html")
@@include("partials/vue/avatar.html")
@@include("partials/vue/timeline.html")
@@include("partials/vue/accordion.html")
@@include("partials/vue/tabs.html")
@@include("partials/vue/drawer.html")
@@include("partials/vue/toasts.html")
@@include("partials/vue/cards.html")
@@include("partials/vue/modals.html")
@@include("partials/vue/confirm-dialog.html")

                <GnModal v-model:open="modalOpen" title="Demo modal window">
                  <p class="text">Любой контент: текст, формы, списки.</p>
                  <GnInput v-model="name" label="Project name" placeholder="Launch Plan" />
                  <GnTextarea v-model="name" label="Description" placeholder="Optional" />
                  <template #actions>
                    <GnButton variant="primary" @click="modalOpen = false">Cancel</GnButton>
                    <GnButton variant="success" @click="save">Apply</GnButton>
                  </template>
                </GnModal>

                <GnDrawer v-model:open="drawerOpen" title="Details" position="right">
                  <p class="text">Context panel for quick edits, metadata, and secondary flows.</p>
                  <GnDescriptionList :items="[{ term: 'Status', value: 'Active' }, { term: 'Owner', value: 'Design System' }, { term: 'Updated', value: 'Today' }]" />
                </GnDrawer>

                <GnDrawer v-model:open="leftDrawerOpen" title="Navigation" position="left">
                  <ul class="list-menu">
                    <li class="list-item"><button class="list-action" type="button"><span class="list-label">Overview</span></button></li>
                    <li class="list-item"><button class="list-action" type="button"><span class="list-label">Activity</span></button></li>
                    <li class="list-item"><button class="list-action" type="button"><span class="list-label">Settings</span></button></li>
                  </ul>
                </GnDrawer>

                <GnConfirmDialog
                  v-model:open="confirmOpen"
                  title="Apply this change?"
                  message="This action requires confirmation."
                  confirm-variant="success"
                  @confirm="confirmAction"
                />
                  </div>
                </div>
              </main>
            </template>
          </GnNavigationShell>
        </GnToastProvider>
      `
    }).mount("#app");
  </script>
  <script>
    document.addEventListener("DOMContentLoaded", () => {
      setTimeout(() => {
        const edstr = editableString(document.querySelector(".editable-example"));
        if (edstr && edstr.editableString) {
          edstr.editableString.onSwitch(component => console.log("SWITCH", component));
          edstr.editableString.onChange(component => console.log("onChange", component.value));
        }
      }, 100);
    });
  </script>
  <script src="/js/gnexus-ui-kit.js"></script>
  <script src="/assets/libs/highlight/highlight.min.js"></script>
</body>
</html>