Refactor card widgets to use a shared base component (#2781)

Supersedes #1801.

Implements the proposal from
https://github.com/openhab/openhab-webui/pull/1801#issuecomment-1475172733.

-----

Signed-off-by: Florian Hotze <florianh_dev@icloud.com>
dependabot/npm_and_yarn/bundles/org.openhab.ui.habpanel/web/serve-static-1.16.2
Florian Hotze 2024-10-01 17:45:35 +02:00 committed by GitHub
parent 4785cfaeb9
commit dcbc549245
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
34 changed files with 726 additions and 290 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

View File

@ -39,6 +39,7 @@ source: https://github.com/openhab/openhab-webui/edit/main/bundles/org.openhab.u
| Component | Name | Description |
|--------|------|-------------|
| [`oh-card`](./oh-card.html) | [Card](./oh-card.html) | The basic structure of all card widgets, providing title and footer and requiring a content slot |
| [`oh-clock-card`](./oh-clock-card.html) | [Digital Clock Card](./oh-clock-card.html) | Display a digital clock in a card |
| [`oh-colorpicker-card`](./oh-colorpicker-card.html) | [Color Picker Card](./oh-colorpicker-card.html) | Display a color picker in a card |
| [`oh-gauge-card`](./oh-gauge-card.html) | [Gauge Card](./oh-gauge-card.html) | Display a read-only gauge in a card to visualize a quantifiable item |

View File

@ -46,7 +46,7 @@ Position widgets on a canvas layout with arbitrary position and size down to pix
</PropBlock>
<PropBlock type="INTEGER" name="screenHeight" label="Screen Height">
<PropDescription>
Screen width in pixels (default 720)
Screen height in pixels (default 720)
</PropDescription>
</PropBlock>
<PropBlock type="BOOLEAN" name="scale" label="Scaling">

View File

@ -0,0 +1,505 @@
---
title: oh-card - Card
component: oh-card
label: Card
description: The basic structure of all card widgets, providing title and footer and requiring a content slot
source: https://github.com/openhab/openhab-webui/edit/main/bundles/org.openhab.ui/doc/components/oh-card.md
prev: /docs/ui/components/
---
# oh-card - Card
<!-- Put a screenshot here if relevant:
![](./images/oh-card/header.jpg)
-->
[[toc]]
The `oh-card` component provides the basic structure for all other card widgets.
It is providing a default implementation for both title and footer, and requires the content to be defined in the `content` slot.
Optionally, header and footer can be overwritten by providing the `header` and `footer` slots (see [Slots](#slots)).
`oh-card` also provides full control over its style as well as header, content and footer style (see [Style](#style)).
## Configuration
<!-- DO NOT REMOVE the following comments -->
<!-- GENERATED props -->
### Card
<div class="props">
<PropGroup name="card" label="Card">
Parameters of the card
<PropBlock type="TEXT" name="title" label="Title">
<PropDescription>
Title of the card
</PropDescription>
</PropBlock>
<PropBlock type="TEXT" name="footer" label="Footer text">
<PropDescription>
Footer of the card
</PropDescription>
</PropBlock>
<PropBlock type="BOOLEAN" name="noBorder" label="No Border">
<PropDescription>
Do not render the card border
</PropDescription>
</PropBlock>
<PropBlock type="BOOLEAN" name="noShadow" label="No Shadow">
<PropDescription>
Do not render a shadow effect to the card
</PropDescription>
</PropBlock>
<PropBlock type="BOOLEAN" name="outline" label="Outline">
<PropDescription>
Show the card outline
</PropDescription>
</PropBlock>
</PropGroup>
</div>
### Action
<div class="props">
<PropGroup name="actions" label="Action">
Action to perform when the element is clicked
<PropBlock type="TEXT" name="action" label="Action">
<PropDescription>
Type of action to perform
</PropDescription>
<PropOptions>
<PropOption value="navigate" label="Navigate to page" />
<PropOption value="command" label="Send command" />
<PropOption value="toggle" label="Toggle Item" />
<PropOption value="options" label="Command options" />
<PropOption value="rule" label="Run scene, script or rule" />
<PropOption value="popup" label="Open popup" />
<PropOption value="popover" label="Open popover" />
<PropOption value="sheet" label="Open sheet" />
<PropOption value="photos" label="Open photo browser" />
<PropOption value="group" label="Group details" />
<PropOption value="analyzer" label="Analyze item(s)" />
<PropOption value="url" label="Navigate to external URL" />
<PropOption value="http" label="Send HTTP request" />
<PropOption value="variable" label="Set Variable" />
</PropOptions>
</PropBlock>
<PropBlock type="TEXT" name="actionUrl" label="Action URL" context="url">
<PropDescription>
URL to navigate to or to send HTTP request to
</PropDescription>
</PropBlock>
<PropBlock type="BOOLEAN" name="actionUrlSameWindow" label="Open in same tab/window">
<PropDescription>
Open the URL in the same tab/window instead of a new one. This will exit the app.
</PropDescription>
</PropBlock>
<PropBlock type="TEXT" name="actionHttpMethod" label="HTTP Method">
<PropDescription>
HTTP method to use for the request
</PropDescription>
<PropOptions>
<PropOption value="GET" label="GET" />
<PropOption value="POST" label="POST" />
<PropOption value="PUT" label="PUT" />
<PropOption value="DELETE" label="DELETE" />
</PropOptions>
</PropBlock>
<PropBlock type="TEXT" name="actionHttpBody" label="HTTP Body">
<PropDescription>
Body to send with the request
</PropDescription>
</PropBlock>
<PropBlock type="TEXT" name="actionItem" label="Action Item" context="item">
<PropDescription>
Item to perform the action on
</PropDescription>
</PropBlock>
<PropBlock type="TEXT" name="actionCommand" label="Action Command">
<PropDescription>
Command to send to the Item. If "Toogle Item" is selected as the action, only send the command when the state is different
</PropDescription>
</PropBlock>
<PropBlock type="TEXT" name="actionCommandAlt" label="Action Toggle Command">
<PropDescription>
Command to send to the Item when "Toggle Item" is selected as the action, and the Item's state is equal to the command above
</PropDescription>
</PropBlock>
<PropBlock type="TEXT" name="actionOptions" label="Command Options">
<PropDescription>
Comma-separated list of options; if omitted, retrieve the command options from the Item dynamically. Use <code>value=label</code> format to provide a label different than the option.
</PropDescription>
</PropBlock>
<PropBlock type="TEXT" name="actionRule" label="Scene, Script or Rule" context="rule">
<PropDescription>
Scene, Script or Rule to run
</PropDescription>
</PropBlock>
<PropBlock type="TEXT" name="actionRuleContext" label="Context" context="script">
<PropDescription>
Object representing the optional context to pass. Edit in YAML or provide a JSON object, e.g. <code>{ "param1": "value1", "param2": { "subkey1": "testing", "subkey2": 123 } }</code>.
</PropDescription>
</PropBlock>
<PropBlock type="TEXT" name="actionPage" label="Page" context="page">
<PropDescription>
Page to navigate to
</PropDescription>
</PropBlock>
<PropBlock type="TEXT" name="actionPageTransition" label="Transition Effect">
<PropDescription>
Use a specific <a class="external text-color-blue" target="_blank" href="https://framework7.io/docs/view.html#custom-page-transitions">page transition animation</a>
</PropDescription>
<PropOptions>
<PropOption value="f7-circle" label="Circle" />
<PropOption value="f7-cover" label="Cover" />
<PropOption value="f7-cover-v" label="Cover from bottom" />
<PropOption value="f7-dive" label="Dive" />
<PropOption value="f7-fade" label="Fade" />
<PropOption value="f7-flip" label="Flip" />
<PropOption value="f7-parallax" label="Parallax" />
<PropOption value="f7-push" label="Push" />
</PropOptions>
</PropBlock>
<PropBlock type="TEXT" name="actionModal" label="Modal Page or Widget" context="pagewidget">
<PropDescription>
Page or widget to display in the modal
</PropDescription>
</PropBlock>
<PropBlock type="TEXT" name="actionModalConfig" label="Modal component configuration" context="props">
<PropDescription>
Configuration (prop values) for the target modal page or widget
</PropDescription>
</PropBlock>
<PropBlock type="TEXT" name="actionPhotos" label="Images to show">
<PropDescription>
Array of URLs or objects representing the images. Auto-refresh is not supported.<br />Edit in YAML, e.g.<br /><code><pre>- item: ImageItem1<br /> caption: Camera</pre></code>or provide a JSON array, e.g.<br /><code>[ "url1", { "item": "ImageItem1", "caption": "Camera" } ]</code><br />Objects are in the <a class="external text-color-blue" target="_blank" href="https://framework7.io/docs/photo-browser.html#photos-array">photos array format</a> with an additional <code>item</code> property to specify an item to view.
</PropDescription>
</PropBlock>
<PropBlock type="TEXT" name="actionPhotoBrowserConfig" label="Photo browser configuration">
<PropDescription>
Configuration for the photo browser.<br />Edit in YAML or provide a JSON object, e.g.<br /><code>{ "exposition": false, "type": "popup", "theme": "dark" }</code><br /> See <a class="external text-color-blue" target="_blank" href="https://framework7.io/docs/photo-browser.html#photo-browser-parameters">photo browser parameters</a> (not all are supported).
</PropDescription>
</PropBlock>
<PropBlock type="TEXT" name="actionGroupPopupItem" label="Group Popup Item" context="item">
<PropDescription>
Group Item whose members to show in a popup
</PropDescription>
</PropBlock>
<PropBlock type="TEXT" name="actionAnalyzerItems" label="Item(s) to Analyze" required="true" context="item">
<PropDescription>
Start analyzing with the specified (set of) Item(s)
</PropDescription>
</PropBlock>
<PropBlock type="TEXT" name="actionAnalyzerChartType" label="Chart Type">
<PropDescription>
The initial analyzing period - dynamic or a predefined fixed period: day, week, month or year
</PropDescription>
<PropOptions>
<PropOption value="(empty)" label="Dynamic" />
<PropOption value="day" label="Day" />
<PropOption value="isoWeek" label="Week (starting on Mondays)" />
<PropOption value="month" label="Month" />
<PropOption value="year" label="Year" />
</PropOptions>
</PropBlock>
<PropBlock type="TEXT" name="actionAnalyzerCoordSystem" label="Initial Coordinate System">
<PropDescription>
The initial coordinate system of the analyzer - time, aggregate or calendar (only time is supported for dynamic periods)
</PropDescription>
<PropOptions>
<PropOption value="time" label="Time" />
<PropOption value="aggregate" label="Aggregate" />
<PropOption value="calendar" label="Calendar" />
</PropOptions>
</PropBlock>
<PropBlock type="TEXT" name="actionConfirmation" label="Action Confirmation">
<PropDescription>
Shows a dialog or sheet to ask for confirmation before the action is executed. Can either be a text to show in the dialog or a JSON object <code>{ type: "dialog", title: "Confirm", text: "Are you sure?" }</code> or <code>{ type: "sheet", text: "Confirm", color: "green" }</code>
</PropDescription>
</PropBlock>
<PropBlock type="TEXT" name="actionFeedback" label="Action Feedback">
<PropDescription>
Shows a toast popup when the action has been executed. Can either be a text to show or a JSON object including some of the <a class="external text-color-blue" target="_blank" href="https://framework7.io/docs/toast.html#toast-parameters">supported parameters</a>
</PropDescription>
</PropBlock>
<PropBlock type="TEXT" name="actionVariable" label="Variable">
<PropDescription>
The variable name to set
</PropDescription>
</PropBlock>
<PropBlock type="TEXT" name="actionVariableValue" label="Variable Value">
<PropDescription>
The value to set the variable to
</PropDescription>
</PropBlock>
<PropBlock type="TEXT" name="actionVariableKey" label="Variable Key">
<PropDescription>
Consider the variable value is an object and set the corresponding deep property within that object using a key syntax. Examples: <code>user.name</code>, <code>user[0].address[1].street</code>, <code>[0]</code>, <code>[0].label</code>. The inner property and its parent hierarchy will be created if missing.
</PropDescription>
</PropBlock>
</PropGroup>
</div>
### Tap Hold
<div class="props">
<PropGroup name="taphold_actions" label="Tap Hold">
Action performed when tapping and holding card (or calling contextual menu on desktop)
<PropBlock type="TEXT" name="taphold_action" label="Action">
<PropDescription>
Type of action to perform
</PropDescription>
<PropOptions>
<PropOption value="navigate" label="Navigate to page" />
<PropOption value="command" label="Send command" />
<PropOption value="toggle" label="Toggle Item" />
<PropOption value="options" label="Command options" />
<PropOption value="rule" label="Run scene, script or rule" />
<PropOption value="popup" label="Open popup" />
<PropOption value="popover" label="Open popover" />
<PropOption value="sheet" label="Open sheet" />
<PropOption value="photos" label="Open photo browser" />
<PropOption value="group" label="Group details" />
<PropOption value="analyzer" label="Analyze item(s)" />
<PropOption value="url" label="Navigate to external URL" />
<PropOption value="http" label="Send HTTP request" />
<PropOption value="variable" label="Set Variable" />
</PropOptions>
</PropBlock>
<PropBlock type="TEXT" name="taphold_actionUrl" label="Action URL" context="url">
<PropDescription>
URL to navigate to or to send HTTP request to
</PropDescription>
</PropBlock>
<PropBlock type="BOOLEAN" name="taphold_actionUrlSameWindow" label="Open in same tab/window">
<PropDescription>
Open the URL in the same tab/window instead of a new one. This will exit the app.
</PropDescription>
</PropBlock>
<PropBlock type="TEXT" name="taphold_actionHttpMethod" label="HTTP Method">
<PropDescription>
HTTP method to use for the request
</PropDescription>
<PropOptions>
<PropOption value="GET" label="GET" />
<PropOption value="POST" label="POST" />
<PropOption value="PUT" label="PUT" />
<PropOption value="DELETE" label="DELETE" />
</PropOptions>
</PropBlock>
<PropBlock type="TEXT" name="taphold_actionHttpBody" label="HTTP Body">
<PropDescription>
Body to send with the request
</PropDescription>
</PropBlock>
<PropBlock type="TEXT" name="taphold_actionItem" label="Action Item" context="item">
<PropDescription>
Item to perform the action on
</PropDescription>
</PropBlock>
<PropBlock type="TEXT" name="taphold_actionCommand" label="Action Command">
<PropDescription>
Command to send to the Item. If "Toogle Item" is selected as the action, only send the command when the state is different
</PropDescription>
</PropBlock>
<PropBlock type="TEXT" name="taphold_actionCommandAlt" label="Action Toggle Command">
<PropDescription>
Command to send to the Item when "Toggle Item" is selected as the action, and the Item's state is equal to the command above
</PropDescription>
</PropBlock>
<PropBlock type="TEXT" name="taphold_actionOptions" label="Command Options">
<PropDescription>
Comma-separated list of options; if omitted, retrieve the command options from the Item dynamically. Use <code>value=label</code> format to provide a label different than the option.
</PropDescription>
</PropBlock>
<PropBlock type="TEXT" name="taphold_actionRule" label="Scene, Script or Rule" context="rule">
<PropDescription>
Scene, Script or Rule to run
</PropDescription>
</PropBlock>
<PropBlock type="TEXT" name="taphold_actionRuleContext" label="Context" context="script">
<PropDescription>
Object representing the optional context to pass. Edit in YAML or provide a JSON object, e.g. <code>{ "param1": "value1", "param2": { "subkey1": "testing", "subkey2": 123 } }</code>.
</PropDescription>
</PropBlock>
<PropBlock type="TEXT" name="taphold_actionPage" label="Page" context="page">
<PropDescription>
Page to navigate to
</PropDescription>
</PropBlock>
<PropBlock type="TEXT" name="taphold_actionPageTransition" label="Transition Effect">
<PropDescription>
Use a specific <a class="external text-color-blue" target="_blank" href="https://framework7.io/docs/view.html#custom-page-transitions">page transition animation</a>
</PropDescription>
<PropOptions>
<PropOption value="f7-circle" label="Circle" />
<PropOption value="f7-cover" label="Cover" />
<PropOption value="f7-cover-v" label="Cover from bottom" />
<PropOption value="f7-dive" label="Dive" />
<PropOption value="f7-fade" label="Fade" />
<PropOption value="f7-flip" label="Flip" />
<PropOption value="f7-parallax" label="Parallax" />
<PropOption value="f7-push" label="Push" />
</PropOptions>
</PropBlock>
<PropBlock type="TEXT" name="taphold_actionModal" label="Modal Page or Widget" context="pagewidget">
<PropDescription>
Page or widget to display in the modal
</PropDescription>
</PropBlock>
<PropBlock type="TEXT" name="taphold_actionModalConfig" label="Modal component configuration" context="props">
<PropDescription>
Configuration (prop values) for the target modal page or widget
</PropDescription>
</PropBlock>
<PropBlock type="TEXT" name="taphold_actionPhotos" label="Images to show">
<PropDescription>
Array of URLs or objects representing the images. Auto-refresh is not supported.<br />Edit in YAML, e.g.<br /><code><pre>- item: ImageItem1<br /> caption: Camera</pre></code>or provide a JSON array, e.g.<br /><code>[ "url1", { "item": "ImageItem1", "caption": "Camera" } ]</code><br />Objects are in the <a class="external text-color-blue" target="_blank" href="https://framework7.io/docs/photo-browser.html#photos-array">photos array format</a> with an additional <code>item</code> property to specify an item to view.
</PropDescription>
</PropBlock>
<PropBlock type="TEXT" name="taphold_actionPhotoBrowserConfig" label="Photo browser configuration">
<PropDescription>
Configuration for the photo browser.<br />Edit in YAML or provide a JSON object, e.g.<br /><code>{ "exposition": false, "type": "popup", "theme": "dark" }</code><br /> See <a class="external text-color-blue" target="_blank" href="https://framework7.io/docs/photo-browser.html#photo-browser-parameters">photo browser parameters</a> (not all are supported).
</PropDescription>
</PropBlock>
<PropBlock type="TEXT" name="taphold_actionGroupPopupItem" label="Group Popup Item" context="item">
<PropDescription>
Group Item whose members to show in a popup
</PropDescription>
</PropBlock>
<PropBlock type="TEXT" name="taphold_actionAnalyzerItems" label="Item(s) to Analyze" required="true" context="item">
<PropDescription>
Start analyzing with the specified (set of) Item(s)
</PropDescription>
</PropBlock>
<PropBlock type="TEXT" name="taphold_actionAnalyzerChartType" label="Chart Type">
<PropDescription>
The initial analyzing period - dynamic or a predefined fixed period: day, week, month or year
</PropDescription>
<PropOptions>
<PropOption value="(empty)" label="Dynamic" />
<PropOption value="day" label="Day" />
<PropOption value="isoWeek" label="Week (starting on Mondays)" />
<PropOption value="month" label="Month" />
<PropOption value="year" label="Year" />
</PropOptions>
</PropBlock>
<PropBlock type="TEXT" name="taphold_actionAnalyzerCoordSystem" label="Initial Coordinate System">
<PropDescription>
The initial coordinate system of the analyzer - time, aggregate or calendar (only time is supported for dynamic periods)
</PropDescription>
<PropOptions>
<PropOption value="time" label="Time" />
<PropOption value="aggregate" label="Aggregate" />
<PropOption value="calendar" label="Calendar" />
</PropOptions>
</PropBlock>
<PropBlock type="TEXT" name="taphold_actionConfirmation" label="Action Confirmation">
<PropDescription>
Shows a dialog or sheet to ask for confirmation before the action is executed. Can either be a text to show in the dialog or a JSON object <code>{ type: "dialog", title: "Confirm", text: "Are you sure?" }</code> or <code>{ type: "sheet", text: "Confirm", color: "green" }</code>
</PropDescription>
</PropBlock>
<PropBlock type="TEXT" name="taphold_actionFeedback" label="Action Feedback">
<PropDescription>
Shows a toast popup when the action has been executed. Can either be a text to show or a JSON object including some of the <a class="external text-color-blue" target="_blank" href="https://framework7.io/docs/toast.html#toast-parameters">supported parameters</a>
</PropDescription>
</PropBlock>
<PropBlock type="TEXT" name="taphold_actionVariable" label="Variable">
<PropDescription>
The variable name to set
</PropDescription>
</PropBlock>
<PropBlock type="TEXT" name="taphold_actionVariableValue" label="Variable Value">
<PropDescription>
The value to set the variable to
</PropDescription>
</PropBlock>
<PropBlock type="TEXT" name="taphold_actionVariableKey" label="Variable Key">
<PropDescription>
Consider the variable value is an object and set the corresponding deep property within that object using a key syntax. Examples: <code>user.name</code>, <code>user[0].address[1].street</code>, <code>[0]</code>, <code>[0].label</code>. The inner property and its parent hierarchy will be created if missing.
</PropDescription>
</PropBlock>
</PropGroup>
</div>
<!-- GENERATED /props -->
## Slots
You need to define either one of these two slots:
- `content`: The default slot for content, which will then be rendered inside a `f7-card-content` element.
- `content-root`: The slot for content that should be rendered directly inside the card, without any additional wrapping element.
Optionally, you can define these slots:
- `header`: The slot for the header content, which will replace the default header.
- `footer`: The slot for the footer content, which will replace the default footer.
## Style
`oh-card` provides full control over the style of itself as well as the header, content and footer.
The card itself can be styled through the `style` and `class` config properties,
while the header, content and footer can be styled through the `headerStyle`, `headerClass`, `contentStyle`, `contentClass`, `footerStyle` and `footerClass` properties.
## Example
![](./images/oh-card/example.png)
This card can be created using the following YAML definition:
```yaml
component: oh-card
config:
title: Title
footer: Footer
style: {} # Card style
class: [] # Card classes
headerStyle: {} # Header style
headerClass: [] # Header classes
contentStyle: {} # Content style
contentClass: [] # Content classes
footerStyle: {} # Footer style
footerClass: [] # Footer classes
slots:
content:
- component: oh-button
config:
text: Content
```
Without using the `oh-card` component, the same card can be created by directly using the Framework7 components:
```yaml
component: f7-card
config:
style: {} # Card style
class: [] # Card classes
slots:
default:
- component: f7-card-header
config:
style: {} # Header style
class: [] # Header classes
slots:
default:
- component: Label
config:
text: Title
- component: f7-card-content
config:
style: {} # Content style
class: [] # Content classes
slots:
default:
- component: oh-button
config:
text: Content
- component: f7-card-footer
config:
style: {} # Footer style
class: [] # Footer classes
slots:
default:
- component: Label
config:
text: Footer
```

View File

@ -80,7 +80,7 @@ Display a slider in a card to control an item
Minimum interval between values
</PropDescription>
</PropBlock>
<PropBlock type="DECIMAL" name="vertical" label="Vertical">
<PropBlock type="BOOLEAN" name="vertical" label="Vertical">
<PropDescription>
Display the slider vertically
</PropDescription>

View File

@ -90,7 +90,7 @@ A cell expanding to a big vertical slider
Minimum interval between values
</PropDescription>
</PropBlock>
<PropBlock type="DECIMAL" name="vertical" label="Vertical">
<PropBlock type="BOOLEAN" name="vertical" label="Vertical">
<PropDescription>
Display the slider vertically
</PropDescription>

View File

@ -85,7 +85,7 @@ Display a slider control in a list
Minimum interval between values
</PropDescription>
</PropBlock>
<PropBlock type="DECIMAL" name="vertical" label="Vertical">
<PropBlock type="BOOLEAN" name="vertical" label="Vertical">
<PropDescription>
Display the slider vertically
</PropDescription>

View File

@ -48,7 +48,7 @@ Slider control, allows to pick a number value on a scale
Minimum interval between values
</PropDescription>
</PropBlock>
<PropBlock type="DECIMAL" name="vertical" label="Vertical">
<PropBlock type="BOOLEAN" name="vertical" label="Vertical">
<PropDescription>
Display the slider vertically
</PropDescription>

View File

@ -159,13 +159,15 @@ export function pt (name, label, description) {
* @param {string} name the name of the widget (in kebab case)
* @param {string} label the untranslated (English) name of the widget
* @param {string} description the untranslated (English) description of the widget
* @param {string} icon an optional icon to illustrate the widget, used for map/plan markers
* @param {string} [icon] an optional icon to illustrate the widget, used for map/plan markers
* @param {boolean} [hidden=false] whether the widget is hidden and should not be shown in the widget picker
*/
export function WidgetDefinition (name, label, description, icon) {
export function WidgetDefinition (name, label, description, icon, hidden = false) {
this.name = name
this.label = label
this.description = description
if (icon) this.icon = icon
this.hidden = hidden
this.props = {
parameterGroups: [],
parameters: []

View File

@ -85,7 +85,7 @@ export function OhCanvasLayoutDefinition () {
])
.paramGroup(pg('screenSettings', 'Screen Settings'), [
pn('screenWidth', 'Screen Width', 'Screen width in pixels (default 1280)'),
pn('screenHeight', 'Screen Height', 'Screen width in pixels (default 720)'),
pn('screenHeight', 'Screen Height', 'Screen height in pixels (default 720)'),
pb('scale', 'Scaling', 'Scale content to screen width (can lead to unexpected styling issues) (default false)'),
pt('imageUrl', 'Image URL', 'The URL of the image to display as background').c('url'),
pt('imageSrcSet', 'Image Source Set', 'The src-set attribute of background image element to take into account multiple device resolutions. For example: "/static/floorplans/floor-0.jpg, /static/floorplans/floor-0@2x.jpg 2x"')

View File

@ -13,6 +13,12 @@ export const CardParameters = () => [
pb('outline', 'Outline', 'Show the card outline').a()
]
// OhCard
export const OhCardDefinition = () => new WidgetDefinition('oh-card', 'Card', 'The basic structure of all card widgets, providing title and footer and requiring a content slot', undefined, true)
.paramGroup(CardParameterGroup(), CardParameters())
.paramGroup(actionGroup(), actionParams())
.paramGroup(actionGroup('Tap Hold', 'Action performed when tapping and holding card (or calling contextual menu on desktop)', 'taphold'), actionParams(null, 'taphold'), true)
// OhLabelCard
import TrendParameters from '../system/trend.js'
export const OhLabelCardDefinition = () => new WidgetDefinition('oh-label-card', 'Label Card', 'Display the state of an item in a card')

View File

@ -5,7 +5,7 @@ export default () => [
pd('min', 'Min', 'Minimum value'),
pd('max', 'Max', 'Maximum value'),
pd('step', 'Step', 'Minimum interval between values'),
pd('vertical', 'Vertical', 'Display the slider vertically'),
pb('vertical', 'Vertical', 'Display the slider vertically'),
pb('label', 'Display Label', 'Display a label above the slider knob while sliding'),
pb('scale', 'Display Scale', 'Display a scale on the slider'),
pn('scaleSteps', 'Scale steps', 'Number of (major) scale markers'),

View File

@ -8,6 +8,12 @@
<generic-widget-component v-else :context="childContext(slotComponent)" v-for="(slotComponent, idx) in slotComponents" :slot="slotName" :key="slotName + '-' + idx" @command="onCommand" />
</template>
</component>
<oh-card v-else-if="componentType && componentType === 'oh-card' && visible" :context="context">
<!-- eslint-disable-next-line vue/no-unused-vars -->
<template v-for="(slotComponents, slotName) in context.component.slots" #[slotName]>
<generic-widget-component :context="childContext(slotComponent)" v-for="(slotComponent, idx) in slotComponents" :slot="slotName" :key="slotName + '-' + idx" @command="onCommand" />
</template>
</oh-card>
<generic-widget-component v-else-if="componentType && componentType.startsWith('widget:') && visible" :context="childWidgetContext()" @command="onCommand" />
<component v-else-if="componentType && componentType.startsWith('oh-') && visible" :is="componentType" :context="context" @command="onCommand" />
<div v-else-if="componentType && componentType === 'Label' && visible" :class="config.class" :style="config.style">

View File

@ -1,5 +1,6 @@
/* Add any new widget to this file - the name of the export should be "OhSomething" */
export { default as OhCard } from './oh-card.vue'
export { default as OhEquipmentCard } from './oh-equipment-card.vue'
export { default as OhLabelCard } from './oh-label-card.vue'
export { default as OhToggleCard } from './oh-toggle-card.vue'

View File

@ -0,0 +1,37 @@
<template>
<f7-card :no-border="config.noBorder" :no-shadow="config.noShadow" :outline="config.outline" :style="config.style" :class="config.class">
<slot name="header">
<f7-card-header v-if="config.title" :style="config.headerStyle" :class="config.headerClass">
<div>{{ config.title }}</div>
</f7-card-header>
</slot>
<slot name="content-root">
<f7-card-content @click.native="config.action ? performAction : ''" :style="{ ...contentStyle, ...config.contentStyle}" :class="[ ...(Array.isArray(contentClass) ? contentClass : ['padding']), ...(Array.isArray(config.contentClass) ? config.contentClass : []) ]">
<slot name="content" />
</f7-card-content>
</slot>
<slot name="footer">
<f7-card-footer v-if="config.footer && !Array.isArray(config.footer)">
{{ config.footer }}
</f7-card-footer>
<f7-card-footer v-else-if="config.footer && Array.isArray(config.footer)">
<span v-for="text in config.footer" :key="text">
{{ text }}
</span>
</f7-card-footer>
</slot>
</f7-card>
</template>
<script>
import mixin from '../widget-mixin'
import { actionsMixin } from '@/components/widgets/widget-actions'
import { OhCardDefinition } from '@/assets/definitions/widgets/standard/cards'
export default {
mixins: [mixin, actionsMixin],
widget: OhCardDefinition,
props: ['context', 'contentStyle', 'contentClass'],
slotProps: ['header', 'content', 'content-root', 'footer']
}
</script>

View File

@ -1,9 +1,6 @@
<template>
<f7-card :no-border="config.noBorder" :no-shadow="config.noShadow" :outline="config.outline" :style="{ background: config.background }">
<f7-card-header v-if="config.title">
<div>{{ config.title }}</div>
</f7-card-header>
<f7-card-content @click.native="performAction" class="clock-card-content text-align-center">
<oh-card :context="context" :content-class="['clock-card-content', 'text-align-center']">
<template #content>
<f7-row v-if="config.showDate && config.datePos !== 'below'">
<f7-col>
<oh-clock :context="{ component: { component: 'oh-clock', config: {} }}" :style="{ 'font-size': config.dateFontSize || '1vw', 'font-weight': config.dateFontWeight || 'normal' }" :format="config.dateFormat" />
@ -19,23 +16,22 @@
<oh-clock :context="{ component: { component: 'oh-clock', config: {} }}" :style="{ 'font-size': config.dateFontSize || '1vw', 'font-weight': config.dateFontWeight || 'normal' }" :format="config.dateFormat" />
</f7-col>
</f7-row>
</f7-card-content>
<oh-card-footer v-if="config.footer" :texts="config.footer" />
</f7-card>
</template>
</oh-card>
</template>
<script>
import mixin from '../widget-mixin'
import { actionsMixin } from '../widget-actions'
import OhCard from '@/components/widgets/standard/oh-card.vue'
import OhClock from '../system/oh-clock.vue'
import OhCardFooter from '../system/oh-card-footer.vue'
import { OhClockCardDefinition } from '@/assets/definitions/widgets/standard/cards'
export default {
mixins: [mixin, actionsMixin],
components: {
OhClock,
OhCardFooter
OhCard,
OhClock
},
widget: OhClockCardDefinition
}

View File

@ -1,29 +1,22 @@
<template>
<f7-card :no-border="config.noBorder" :no-shadow="config.noShadow" :outline="config.outline">
<f7-card-header v-if="config.title">
<div>{{ config.title }}</div>
</f7-card-header>
<f7-card-content class="display-flex justify-content-center">
<oh-card :context="context" :content-class="['display-flex', 'justify-content-center']">
<template #content>
<oh-colorpicker :context="context" @command="onCommand" />
</f7-card-content>
<oh-card-footer v-if="config.footer" :texts="config.footer" />
</f7-card>
</template>
</oh-card>
</template>
<style lang="stylus">
</style>
<script>
import mixin from '../widget-mixin'
import OhCard from '@/components/widgets/standard/oh-card.vue'
import OhColorpicker from '../system/oh-colorpicker.vue'
import OhCardFooter from '../system/oh-card-footer.vue'
import { OhColorpickerCardDefinition } from '@/assets/definitions/widgets/standard/cards'
export default {
mixins: [mixin],
components: {
OhColorpicker,
OhCardFooter
OhCard,
OhColorpicker
},
widget: OhColorpickerCardDefinition,
data () {

View File

@ -1,39 +1,22 @@
<template>
<f7-card :no-border="config.noBorder" :no-shadow="config.noShadow" :outline="config.outline">
<f7-card-header v-if="config.title">
<div>{{ config.title }}</div>
</f7-card-header>
<f7-card-content class="oh-gauge-card display-flex justify-content-center">
<f7-link v-if="config.action" class="oh-gauge-link" @click="performAction">
<oh-gauge :context="childContext(context.component)" />
</f7-link>
<oh-gauge v-else :context="childContext(context.component)" />
</f7-card-content>
<oh-card-footer v-if="config.footer" :texts="config.footer" />
</f7-card>
<oh-card :context="context" :content-class="['oh-gauge-card', 'display-flex', 'justify-content-center']">
<template #content>
<oh-gauge :context="childContext(context.component)" />
</template>
</oh-card>
</template>
<style lang="stylus">
.oh-gauge-link
position absolute
top 0
left 0
width 100%
height 100%
</style>
<script>
import mixin from '../widget-mixin'
import OhCard from '@/components/widgets/standard/oh-card.vue'
import OhGauge from '../system/oh-gauge.vue'
import OhCardFooter from '../system/oh-card-footer.vue'
import { actionsMixin } from '../widget-actions'
import { OhGaugeCardDefinition } from '@/assets/definitions/widgets/standard/cards'
export default {
mixins: [mixin, actionsMixin],
mixins: [mixin],
components: {
OhGauge,
OhCardFooter
OhCard,
OhGauge
},
widget: OhGaugeCardDefinition
}

View File

@ -1,22 +1,13 @@
<template>
<f7-card :no-border="config.noBorder" :no-shadow="config.noShadow" :outline="config.outline">
<f7-card-header v-if="config.title">
<div>{{ config.title }}</div>
</f7-card-header>
<f7-card-content :padding="false" class="oh-image-card">
<f7-list v-if="config.action" class="image-link">
<f7-list-item class="oh-image-clickable" link="#" no-chevron @click="performAction">
<oh-image slot="content-start" :context="childContext(context.component)" />
</f7-list-item>
</f7-list>
<oh-image v-else :context="childContext(context.component)" />
</f7-card-content>
<oh-card-footer v-if="config.footer" :texts="config.footer" />
</f7-card>
<oh-card :context="context" :content-class="['oh-image-card', 'no-padding']">
<template #content>
<oh-image class="oh-image" :context="childContext(context.component)" />
</template>
</oh-card>
</template>
<style lang="stylus">
.oh-image-clickable
.oh-image-card-clickable
--f7-list-item-padding-horizontal: 0px
.oh-image-card
.oh-image
@ -24,25 +15,20 @@
margin-left 5px
margin-right 5px
width calc(100% - 10px)
.image-link
.item-inner
display none
.oh-image
margin-bottom 5px
</style>
<script>
import mixin from '../widget-mixin'
import OhCard from '@/components/widgets/standard/oh-card.vue'
import { actionsMixin } from '../widget-actions'
import OhImage from '../system/oh-image.vue'
import OhCardFooter from '../system/oh-card-footer.vue'
import { OhImageCardDefinition } from '@/assets/definitions/widgets/standard/cards'
export default {
mixins: [mixin, actionsMixin],
components: {
OhImage,
OhCardFooter
OhCard,
OhImage
},
widget: OhImageCardDefinition
}

View File

@ -1,17 +1,12 @@
<template>
<f7-card :no-border="config.noBorder" :no-shadow="config.noShadow" :outline="config.outline">
<f7-card-header v-if="config.title">
<div>{{ config.title }}</div>
</f7-card-header>
<f7-card-content class="padding">
<oh-card :context="context">
<template #content>
<oh-input class="input-card-content" :context="childContext(context.component)" @command="onCommand" />
</f7-card-content>
<oh-card-footer v-if="config.footer" :texts="config.footer" />
</f7-card>
</template>
</oh-card>
</template>
<style lang="stylus">
.input-card-content
width calc(100% - 2*var(--f7-card-content-padding)) !important
.input-field
@ -20,15 +15,15 @@
<script>
import mixin from '../widget-mixin'
import OhInput from '../system/oh-input.vue'
import OhCardFooter from '../system/oh-card-footer.vue'
import OhCard from '@/components/widgets/standard/oh-card.vue'
import { OhInput } from '@/components/widgets/system'
import { OhInputCardDefinition } from '@/assets/definitions/widgets/standard/cards'
export default {
mixins: [mixin],
components: {
OhInput,
OhCardFooter
OhCard,
OhInput
},
widget: OhInputCardDefinition
}

View File

@ -1,29 +1,22 @@
<template>
<f7-card :no-border="config.noBorder" :no-shadow="config.noShadow" :outline="config.outline">
<f7-card-header v-if="config.title">
<div>{{ config.title }}</div>
</f7-card-header>
<f7-card-content class="display-flex justify-content-center">
<oh-card :context="context" :content-class="['display-flex', 'justify-content-center']">
<template #content>
<oh-knob :context="childContext(context.component)" @command="onCommand" />
</f7-card-content>
<oh-card-footer v-if="config.footer" :texts="config.footer" />
</f7-card>
</template>
</oh-card>
</template>
<style lang="stylus">
</style>
<script>
import mixin from '../widget-mixin'
import OhCard from '@/components/widgets/standard/oh-card.vue'
import OhKnob from '../system/oh-knob.vue'
import OhCardFooter from '../system/oh-card-footer.vue'
import { OhKnobCardDefinition } from '@/assets/definitions/widgets/standard/cards'
export default {
mixins: [mixin],
components: {
OhKnob,
OhCardFooter
OhCard,
OhKnob
},
widget: OhKnobCardDefinition
}

View File

@ -1,25 +1,23 @@
<template>
<f7-card :no-border="config.noBorder" :no-shadow="config.noShadow" :outline="config.outline">
<f7-card-header v-if="config.title">
<div>{{ config.title }}</div>
</f7-card-header>
<f7-card-content ref="cardContent" @click.native="performAction" @taphold.native="onTaphold($event)" @contextmenu.native="onContextMenu($event)" class="label-card-content" :style="{ background: config.background }" :class="{ 'vertical-arrangement': config.vertical }">
<oh-trend v-if="config.trendItem" :key="'trend' + config.item" class="trend" :width="($refs.cardContent) ? $refs.cardContent.$el.clientWidth : 0" :context="context" />
<f7-list>
<f7-list-item :link="config.action ? true : false" no-chevron>
<oh-icon slot="media" v-if="config.icon" :icon="config.icon" :height="config.iconSize || 32" :width="config.iconSize || 32" :state="(config.item && config.iconUseState) ? context.store[config.item].state : null" :color="config.iconColor" />
<div :class="config.class">
<span :style="{ 'font-size': config.fontSize || '24px', 'font-weight': config.fontWeight || 'normal' }">
{{ label }}
</span>
</div>
</f7-list-item>
</f7-list>
<!-- <f7-link class="label-link" v-if="config.action">{{context.store[config.item].displayState || context.store[config.item].state}}</f7-link> -->
<!-- <h2>{{context.store[config.item].displayState || context.store[config.item].state}}</h2> -->
</f7-card-content>
<oh-card-footer v-if="config.footer" :texts="config.footer" />
</f7-card>
<oh-card :context="context">
<template #content-root>
<f7-card-content ref="cardContent" @click.native="performAction" @taphold.native="onTaphold($event)" @contextmenu.native="onContextMenu($event)" :class="['label-card-content', (config.vertical ? 'vertical-arrangement' : ''), ...(Array.isArray(config.contentClass) ? config.contentClass : [])]" :style="{ background: config.background, ...config.contentStyle }">
<oh-trend v-if="config.trendItem" :key="'trend' + config.item" class="trend" :width="($refs.cardContent) ? $refs.cardContent.$el.clientWidth : 0" :context="context" />
<f7-list>
<f7-list-item :link="config.action ? true : false" no-chevron>
<oh-icon slot="media" v-if="config.icon" :icon="config.icon" :height="config.iconSize || 32" :width="config.iconSize || 32" :state="(config.item && config.iconUseState) ? context.store[config.item].state : null" :color="config.iconColor" />
<div :class="config.class">
<span :style="{ 'font-size': config.fontSize || '24px', 'font-weight': config.fontWeight || 'normal' }">
{{ label }}
</span>
</div>
</f7-list-item>
</f7-list>
<!-- <f7-link class="label-link" v-if="config.action">{{context.store[config.item].displayState || context.store[config.item].state}}</f7-link> -->
<!-- <h2>{{context.store[config.item].displayState || context.store[config.item].state}}</h2> -->
</f7-card-content>
</template>
</oh-card>
</template>
<style lang="stylus">
@ -48,16 +46,15 @@
<script>
import mixin from '../widget-mixin'
import { actionsMixin } from '../widget-actions'
import { OhLabelCardDefinition } from '@/assets/definitions/widgets/standard/cards'
import OhCard from '@/components/widgets/standard/oh-card.vue'
import OhTrend from '../system/oh-trend'
import OhCardFooter from '../system/oh-card-footer.vue'
import { OhLabelCardDefinition } from '@/assets/definitions/widgets/standard/cards'
export default {
mixins: [mixin, actionsMixin],
components: {
OhTrend,
OhCardFooter
OhCard,
OhTrend
},
widget: OhLabelCardDefinition,
computed: {

View File

@ -1,31 +1,22 @@
<template>
<f7-card :no-border="config.noBorder" :no-shadow="config.noShadow" :outline="config.outline">
<f7-card-header v-if="config.title">
<div>{{ config.title }}</div>
</f7-card-header>
<f7-card-content :class="{ 'slider-card-vertical': config.vertical }">
<oh-card :context="context">
<template #content>
<oh-list :context="childContext(context.component)" v-on="$listeners" />
</f7-card-content>
<oh-card-footer v-if="config.footer" :texts="config.footer" />
</f7-card>
</template>
</oh-card>
</template>
<style lang="stylus">
.slider-card-vertical
height 300px
</style>
<script>
import mixin from '../widget-mixin'
import OhCard from '@/components/widgets/standard/oh-card.vue'
import OhList from '../system/oh-list.vue'
import OhCardFooter from '../system/oh-card-footer.vue'
import { OhListCardDefinition } from '@/assets/definitions/widgets/standard/cards'
export default {
mixins: [mixin],
components: {
OhList,
OhCardFooter
OhCard,
OhList
},
widget: OhListCardDefinition
}

View File

@ -1,41 +1,37 @@
<template>
<f7-card :no-border="config.noBorder" :no-shadow="config.noShadow" :outline="config.outline">
<f7-card-header v-if="config.title">
<div>{{ config.title }}</div>
</f7-card-header>
<f7-card-content>
<oh-card :context="context">
<template #content>
<f7-list v-if="config.artistItem && config.trackItem">
<f7-list-item>
<div class="display-block">
<div class="no-padding no-margin font-weight-normal">
{{ this.context.store[config.artistItem].state }}
{{ context.store[config.artistItem].state }}
</div>
<h3 class="no-padding no-margin">
{{ this.context.store[config.trackItem].state }}
{{ context.store[config.trackItem].state }}
</h3>
</div>
</f7-list-item>
</f7-list>
</f7-card-content>
<f7-card-footer class="display-flex justify-content-center">
<oh-player-controls :context="childContext(context.component)" @command="onCommand" />
</f7-card-footer>
</f7-card>
</template>
<template #footer>
<f7-card-footer class="display-flex justify-content-center">
<oh-player-controls :context="childContext(context.component)" @command="onCommand" />
</f7-card-footer>
</template>
</oh-card>
</template>
<style lang="stylus">
.slider-card-vertical
height 300px
</style>
<script>
import mixin from '../widget-mixin'
import OhCard from '@/components/widgets/standard/oh-card.vue'
import OhPlayerControls from '../system/oh-player-controls.vue'
import { OhPlayerCardDefinition } from '@/assets/definitions/widgets/standard/cards'
export default {
mixins: [mixin],
components: {
OhCard,
OhPlayerControls
},
widget: OhPlayerCardDefinition

View File

@ -1,40 +1,37 @@
<template>
<f7-card :no-border="config.noBorder" :no-shadow="config.noShadow" :outline="config.outline">
<f7-card-header v-if="config.title">
<div>{{ config.title }}</div>
</f7-card-header>
<f7-card-content class="display-flex justify-content-center" :style="{ height: config.vertical ? '10em' : undefined }">
<oh-card :context="context" :content-class="['display-flex', 'justify-content-center', 'oh-rollershutter-card']" :content-style="{ height: config.vertical ? '10em' : undefined }">
<template #content>
<oh-rollershutter :class="{ vertical: config.vertical }" :context="context" @command="onCommand" />
</f7-card-content>
<oh-card-footer v-if="config.footer" :texts="config.footer" />
</f7-card>
</template>
</oh-card>
</template>
<style lang="stylus">
.rollershutter-controls
.button
text-overflow clip
&.vertical
transform rotate(90deg)
transform-origin center
.icon
margin-top 2px
.state
margin-top 2px
transform rotate(-90deg)
.oh-rollershutter-card
.rollershutter-controls
.button
text-overflow clip
&.vertical
transform rotate(90deg)
transform-origin center
.icon
margin-top 2px
.state
margin-top 2px
transform rotate(-90deg)
</style>
<script>
import mixin from '../widget-mixin'
import OhCard from '@/components/widgets/standard/oh-card.vue'
import OhRollershutter from '../system/oh-rollershutter.vue'
import OhCardFooter from '../system/oh-card-footer.vue'
import { OhRollershutterCardDefinition } from '@/assets/definitions/widgets/standard/cards'
export default {
mixins: [mixin],
components: {
OhRollershutter,
OhCardFooter
OhCard,
OhRollershutter
},
widget: OhRollershutterCardDefinition,
data () {

View File

@ -1,26 +1,22 @@
<template>
<f7-card :no-border="config.noBorder" :no-shadow="config.noShadow" :outline="config.outline">
<f7-card-header v-if="config.title">
<div>{{ config.title }}</div>
</f7-card-header>
<f7-card-content class="display-flex justify-content-center">
<oh-card :context="context" :content-class="['display-flex', 'justify-content-center']">
<template #content>
<oh-sipclient v-bind="config" :context="context" />
</f7-card-content>
<oh-card-footer v-if="config.footer" :texts="config.footer" />
</f7-card>
</template>
</oh-card>
</template>
<script>
import mixin from '../widget-mixin'
import OhCard from '@/components/widgets/standard/oh-card.vue'
import OhSipclient from '../system/oh-sipclient.vue'
import OhCardFooter from '../system/oh-card-footer.vue'
import { OhSIPClientCardDefinition } from '@/assets/definitions/widgets/standard/cards'
export default {
mixins: [mixin],
components: {
OhSipclient,
OhCardFooter
OhCard,
OhSipclient
},
widget: OhSIPClientCardDefinition
}

View File

@ -1,13 +1,9 @@
<template>
<f7-card :no-border="config.noBorder" :no-shadow="config.noShadow" :outline="config.outline">
<f7-card-header v-if="config.title">
<div>{{ config.title }}</div>
</f7-card-header>
<f7-card-content class="display-flex justify-content-center" :class="{ 'slider-card-vertical': config.vertical }">
<oh-card :context="context" :content-class="[ (config.vertical ? 'slider-card-vertical' : ''), 'display-flex', 'justify-content-center' ]">
<template #content>
<oh-slider :context="childContext(context.component)" :class="{ 'slider-card-vertical': config.vertical }" @command="onCommand" />
</f7-card-content>
<oh-card-footer v-if="config.footer" :texts="config.footer" />
</f7-card>
</template>
</oh-card>
</template>
<style lang="stylus">
@ -17,15 +13,15 @@
<script>
import mixin from '../widget-mixin'
import OhCard from '@/components/widgets/standard/oh-card.vue'
import OhSlider from '../system/oh-slider.vue'
import OhCardFooter from '../system/oh-card-footer.vue'
import { OhSliderCardDefinition } from '@/assets/definitions/widgets/standard/cards'
export default {
mixins: [mixin],
components: {
OhSlider,
OhCardFooter
OhCard,
OhSlider
},
widget: OhSliderCardDefinition
}

View File

@ -1,13 +1,9 @@
<template>
<f7-card :no-border="config.noBorder" :no-shadow="config.noShadow" :outline="config.outline">
<f7-card-header v-if="config.title">
<div>{{ config.title }}</div>
</f7-card-header>
<f7-card-content class="display-flex justify-content-center">
<oh-card :context="context" :content-class="['display-flex', 'justify-content-center']">
<template #content>
<oh-stepper :context="childContext(context.component)" @command="onCommand" />
</f7-card-content>
<oh-card-footer v-if="config.footer" :texts="config.footer" />
</f7-card>
</template>
</oh-card>
</template>
<style lang="stylus">
@ -17,15 +13,15 @@
<script>
import mixin from '../widget-mixin'
import OhCard from '@/components/widgets/standard/oh-card.vue'
import OhStepper from '../system/oh-stepper.vue'
import OhCardFooter from '../system/oh-card-footer.vue'
import { OhStepperCardDefinition } from '@/assets/definitions/widgets/standard/cards'
export default {
mixins: [mixin],
components: {
OhStepper,
OhCardFooter
OhCard,
OhStepper
},
widget: OhStepperCardDefinition
}

View File

@ -1,31 +1,22 @@
<template>
<f7-card :no-border="config.noBorder" :no-shadow="config.noShadow" :outline="config.outline">
<f7-card-header v-if="config.title">
<div>{{ config.title }}</div>
</f7-card-header>
<f7-card-content :class="{ 'slider-card-vertical': config.vertical }">
<oh-card :context="context" :content-class="['no-padding']">
<template #content>
<oh-swiper :context="childContext(context.component)" v-on="$listeners" />
</f7-card-content>
<oh-card-footer v-if="config.footer" :texts="config.footer" />
</f7-card>
</template>
</oh-card>
</template>
<style lang="stylus">
.slider-card-vertical
height 300px
</style>
<script>
import mixin from '../widget-mixin'
import OhCard from '@/components/widgets/standard/oh-card.vue'
import OhSwiper from '../system/oh-swiper.vue'
import OhCardFooter from '../system/oh-card-footer.vue'
import { OhSwiperCardDefinition } from '@/assets/definitions/widgets/standard/cards'
export default {
mixins: [mixin],
components: {
OhSwiper,
OhCardFooter
OhCard,
OhSwiper
},
widget: OhSwiperCardDefinition
}

View File

@ -1,13 +1,9 @@
<template>
<f7-card :no-border="config.noBorder" :no-shadow="config.noShadow" :outline="config.outline">
<f7-card-header v-if="config.title">
<div>{{ config.title }}</div>
</f7-card-header>
<f7-card-content class="display-flex justify-content-center" style="height: calc(2 * var(--f7-toggle-width))">
<oh-card :context="context" :content-class="['display-flex', 'justify-content-center']" :content-style="{ height: 'calc(2 * var(--f7-toggle-width))' }">
<template #content>
<oh-toggle class="large-vertical-toggle" :context="context" @command="onCommand" />
</f7-card-content>
<oh-card-footer v-if="config.footer" :texts="config.footer" />
</f7-card>
</template>
</oh-card>
</template>
<style lang="stylus">
@ -18,15 +14,15 @@
<script>
import mixin from '../widget-mixin'
import OhCard from '@/components/widgets/standard/oh-card.vue'
import OhToggle from '../system/oh-toggle.vue'
import OhCardFooter from '../system/oh-card-footer.vue'
import { OhToggleCardDefinition } from '@/assets/definitions/widgets/standard/cards'
export default {
mixins: [mixin],
components: {
OhToggle,
OhCardFooter
OhCard,
OhToggle
},
widget: OhToggleCardDefinition,
data () {

View File

@ -1,13 +1,9 @@
<template>
<f7-card :no-border="config.noBorder" :no-shadow="config.noShadow" :outline="config.outline">
<f7-card-header v-if="config.title">
<div>{{ config.title }}</div>
</f7-card-header>
<f7-card-content :padding="false" class="oh-video-card">
<oh-card :context="context" :content-class="['oh-video-card', 'no-padding']">
<template #content>
<oh-video :context="childContext(context.component)" />
</f7-card-content>
<oh-card-footer v-if="config.footer" :texts="config.footer" />
</f7-card>
</template>
</oh-card>
</template>
<style lang="stylus">
@ -24,15 +20,15 @@
<script>
import mixin from '../widget-mixin'
import OhCard from '@/components/widgets/standard/oh-card.vue'
import OhVideo from '../system/oh-video.vue'
import OhCardFooter from '../system/oh-card-footer.vue'
import { OhVideoCardDefinition } from '@/assets/definitions/widgets/standard/cards'
export default {
mixins: [mixin],
components: {
OhVideo,
OhCardFooter
OhCard,
OhVideo
},
widget: OhVideoCardDefinition
}

View File

@ -1,26 +1,22 @@
<template>
<f7-card :no-border="config.noBorder" :no-shadow="config.noShadow" :outline="config.outline">
<f7-card-header v-if="config.title">
<div>{{ config.title }}</div>
</f7-card-header>
<f7-card-content :class="{ 'no-padding': !config.borders }">
<oh-card :context="context" :content-class="!config.borders ? ['no-padding'] : []">
<template #content>
<oh-webframe :context="childContext(context.component)" />
</f7-card-content>
<oh-card-footer v-if="config.footer" :texts="config.footer" />
</f7-card>
</template>
</oh-card>
</template>
<script>
import mixin from '../widget-mixin'
import OhCard from '@/components/widgets/standard/oh-card.vue'
import OhWebframe from '../system/oh-webframe.vue'
import OhCardFooter from '../system/oh-card-footer.vue'
import { OhWebFrameCardDefinition } from '@/assets/definitions/widgets/standard/cards'
export default {
mixins: [mixin],
components: {
OhWebframe,
OhCardFooter
OhCard,
OhWebframe
},
widget: OhWebFrameCardDefinition
}

View File

@ -1,16 +0,0 @@
<template>
<f7-card-footer v-if="texts && !Array.isArray(texts)">
{{ texts }}
</f7-card-footer>
<f7-card-footer v-else-if="texts && Array.isArray(texts)">
<span v-for="text in texts" :key="text">
{{ text }}
</span>
</f7-card-footer>
</template>
<script>
export default {
props: ['texts']
}
</script>

View File

@ -230,7 +230,7 @@ export default {
this.$nextTick(() => actions.destroy())
}
const stdWidgets = (isList) ? StandardListWidgets : (isCells) ? StandardCellWidgets : StandardWidgets
const standardWidgetOptions = Object.keys(stdWidgets).map((k) => {
const standardWidgetOptions = Object.keys(stdWidgets).filter((k) => !stdWidgets[k].widget().hidden).map((k) => {
return {
text: stdWidgets[k].widget().label,
color: 'blue',