JSPM

  • Created
  • Published
  • Downloads 9
  • Score
    100M100P100Q65865F
  • License MIT

A Firebase-powered Content Management System SDK optimized for kiosks with offline support and template management

Package Exports

  • @bigdigital/kiosk-content-sdk
  • @bigdigital/kiosk-content-sdk/dist/index.js

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (@bigdigital/kiosk-content-sdk) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

npm install @bigdigital/kiosk-content-sdk


## Basic Usage

```typescript
import { useKioskContent } from '@bigdigital/kiosk-content-sdk';

function App() {
  const config = {
    projectId: process.env.VITE_FIREBASE_PROJECT_ID,
    apiKey: process.env.VITE_FIREBASE_API_KEY,
    offlineSupport: true, // Enable offline support
    cacheStrategy: "local", // Use local storage for caching
    syncInterval: 300000, // Sync every 5 minutes
    cacheMaxAge: 600000 // Cache expires after 10 minutes
  };

  const { content, loading, error, isSyncing, isOnline } = useKioskContent(config);

  if (loading) return <div>Loading...</div>;
  if (error) return <div>Error: {error.message}</div>;

  return (
    <div>
      {isSyncing && <div>Syncing...</div>}
      {content.map(item => (
        <div key={item.id}>
          <h2>{item.title}</h2>
          <p>{item.description}</p>
        </div>
      ))}
    </div>
  );
}

Components

OfflineIndicator

A customizable component to display the current online/offline status:

import { useKioskContent, OfflineIndicator } from '@bigdigital/kiosk-content-sdk';

function App() {
  const { isOnline } = useKioskContent(config);

  return (
    <div>
      <OfflineIndicator 
        isOnline={isOnline}
        onlineText="Connected" // Optional custom text
        offlineText="Working Offline" // Optional custom text
        className="my-custom-class" // Optional CSS class
        style={{ position: 'fixed', top: '1rem', right: '1rem' }} // Optional inline styles
      />
      {/* Rest of your app */}
    </div>
  );
}

Content and Templates

The SDK provides a powerful system for managing content using templates. Templates define the structure and validation rules for your content, while content instances store the actual data based on these templates.

Creating Template-based Content

import { useKioskContent, useTemplateContent } from '@bigdigital/kiosk-content-sdk';

function ContentManager() {
  const { templates } = useKioskContent(config);

  // Example of creating content based on a template
  const handleCreateContent = async (templateId: string) => {
    const content = {
      title: "New Product",
      description: "Product description",
      type: "template",
      templateId: templateId,
      templateValues: {
        // Values matching the template fields
        name: "Product Name",
        price: 99.99,
        inStock: true
      }
    };

    // Save content using your storage method
    await saveContent(content);
  };
}

Rendering Template-based Content

function ContentDisplay({ contentId }) {
  const { content, template } = useTemplateContent(config, contentId);

  if (!template) return null;

  return (
    <div>
      <h1>{content.title}</h1>

      {/* Render fields by groups */}
      {template.groupOrder.map(groupId => {
        const group = template.groups[groupId];
        const groupFields = group.fieldIds
          .map(fieldId => template.fields[fieldId])
          .filter(Boolean);

        return (
          <div key={groupId} className="field-group">
            <h2>{group.name}</h2>
            {group.description && <p>{group.description}</p>}

            {groupFields.map(field => (
              <div key={field.id}>
                <label>{field.label}</label>
                <div>{content.templateValues?.[field.name]}</div>
              </div>
            ))}
          </div>
        );
      })}

      {/* Render ungrouped fields */}
      {template.ungroupedFieldIds.length > 0 && (
        <div className="ungrouped-fields">
          <h2>Other Information</h2>
          {template.ungroupedFieldIds.map(fieldId => {
            const field = template.fields[fieldId];
            return (
              <div key={field.id}>
                <label>{field.label}</label>
                <div>{content.templateValues?.[field.name]}</div>
              </div>
            );
          })}
        </div>
      )}
    </div>
  );
}

Template Structure

Templates are organized using fields and groups for better content organization:

const template = {
  id: "product-template",
  name: "Product Template",
  description: "Template for product content",
  type: "product",
  // Fields are stored as a record for efficient lookups
  fields: {
    "field-1": {
      id: "field-1",
      name: "name",
      label: "Product Name",
      type: "text",
      validation: { required: true }
    },
    "field-2": {
      id: "field-2",
      name: "price",
      label: "Price",
      type: "number",
      validation: { required: true, min: 0 }
    },
    "field-3": {
      id: "field-3",
      name: "description",
      label: "Description",
      type: "rich-text"
    }
  },
  // Groups organize related fields together
  groups: {
    "group-1": {
      id: "group-1",
      name: "Basic Information",
      description: "Basic product details",
      order: 1,
      fieldIds: ["field-1", "field-2"]
    },
    "group-2": {
      id: "group-2",
      name: "Details",
      description: "Additional product information",
      order: 2,
      fieldIds: ["field-3"]
    }
  },
  // Define the order of groups
  groupOrder: ["group-1", "group-2"],
  // Fields not assigned to any group
  ungroupedFieldIds: [],
  version: 1
};

Field Types

Available field types include:

  • text: Single-line text input
  • rich-text: Multi-line text with formatting
  • number: Numeric input with optional validation
  • boolean: True/false toggle
  • select: Single selection from predefined options
  • multi-select: Multiple selections from options
  • image: Image upload and selection
  • video: Video upload and selection
  • audio: Audio upload and selection
  • date: Date picker
  • color: Color selector

Validation

Fields can include validation rules:

const field = {
  id: "price-field",
  name: "price",
  label: "Price",
  type: "number",
  validation: {
    required: true,
    min: 0,
    max: 1000000,
    customError: "Price must be between $0 and $1,000,000"
  }
};

Template Management

Using Template Content

import { useTemplateContent } from '@bigdigital/kiosk-content-sdk';

function TemplateContent({ templateId }) {
  const { content, template, loading, error } = useTemplateContent(config, templateId);

  if (loading) return <div>Loading...</div>;
  if (error) return <div>Error: {error.message}</div>;

  return (
    <div>
      <h2>{template?.name}</h2>
      {content.map(item => (
        <div key={item.id}>
          {Object.entries(template?.fields || {}).map(([fieldId, field]) => (
            <div key={fieldId}>
              <label>{field.label}</label>
              <div>{item.templateValues?.[field.name]}</div>
            </div>
          ))}
        </div>
      ))}
    </div>
  );
}

Template Structure

Templates now support grouped fields and better organization:

const template = {
  id: "template-1",
  name: "Product Template",
  description: "Template for product content",
  type: "product",
  fields: {
    "field-1": {
      id: "field-1",
      name: "title",
      label: "Product Title",
      type: "text",
      validation: { required: true }
    },
    "field-2": {
      id: "field-2",
      name: "price",
      label: "Product Price",
      type: "number",
      validation: { required: true, min: 0 }
    }
  },
  groups: {
    "group-1": {
      id: "group-1",
      name: "Basic Info",
      description: "Basic product information",
      order: 1,
      fieldIds: ["field-1", "field-2"]
    }
  },
  groupOrder: ["group-1"],
  ungroupedFieldIds: [],
  version: 1
};

Offline Support

import { useOfflineContent } from '@bigdigital/kiosk-content-sdk';

function OfflineApp() {
  const { content, syncStatus, lastSynced, error } = useOfflineContent({
    projectId: "your-project-id",
    apiKey: "your-api-key",
    offlineSupport: true,
    cacheStrategy: "local",
    syncInterval: 300000,
    cacheMaxAge: 600000 // Cache expires after 10 minutes
  });

  return (
    <div>
      <div>Sync Status: {syncStatus}</div>
      {lastSynced && <div>Last Synced: {new Date(lastSynced).toLocaleString()}</div>}
      {error && <div>Error: {error.message}</div>}
      {/* Render content */}
    </div>
  );
}

Manual Sync Control

import { useContentSync } from '@bigdigital/kiosk-content-sdk';

function SyncControl() {
  const { sync, syncStatus, progress, error } = useContentSync(config);

  return (
    <div>
      <button 
        onClick={() => sync({ 
          onError: (err) => console.error(err),
          retryAttempts: 3
        })}
        disabled={syncStatus === 'syncing'}
      >
        Sync Now
      </button>
      {syncStatus === 'syncing' && <div>Progress: {progress}%</div>}
      {error && <div>Error: {error.message}</div>}
    </div>
  );
}

Configuration Options

KioskConfig

interface KioskConfig {
  projectId: string;
  apiKey: string;
  authDomain?: string;
  offlineSupport?: boolean;
  cacheStrategy?: "memory" | "local" | "none";
  syncInterval?: number; // in milliseconds
  cacheMaxAge?: number; // in milliseconds, defaults to 5 minutes
}

Cache Options

interface CacheOptions {
  ttl?: number;
  strategy?: "memory" | "local" | "none";
  validateOnLoad?: boolean;
}

Type Safety

The SDK provides comprehensive TypeScript support:

import type { 
  Content, 
  Template, 
  Field,
  Group,
  FieldType,
  KioskConfig,
  CacheOptions,
  SyncOptions
} from '@bigdigital/kiosk-content-sdk';

API Reference

Hooks

  • useKioskContent: Main hook for content management
  • useTemplateContent: Hook for template-based content
  • useOfflineContent: Hook for offline-first content
  • useContentSync: Hook for manual sync control

Components

  • OfflineIndicator: Display online/offline status

Types

import type { 
  Content,
  Template,
  Field,
  Group,
  FieldType,
  KioskConfig,
  CacheOptions,
  SyncOptions
} from '@bigdigital/kiosk-content-sdk';

Configuration

KioskConfig

interface KioskConfig {
  projectId: string;
  apiKey: string;
  authDomain?: string;
  offlineSupport?: boolean;
  cacheStrategy?: "memory" | "local" | "none";
  syncInterval?: number; // milliseconds
  cacheMaxAge?: number; // milliseconds
}

Cache Options

interface CacheOptions {
  ttl?: number;
  strategy?: "memory" | "local" | "none";
  validateOnLoad?: boolean;
}

Sync Options

interface SyncOptions {
  force?: boolean;
  onProgress?: (progress: number) => void;
  onError?: (error: Error) => void;
  retryAttempts?: number;
}