{"id":25234606,"url":"https://github.com/arthurclemens/glissando","last_synced_at":"2025-10-26T10:30:29.374Z","repository":{"id":40674943,"uuid":"256731603","full_name":"ArthurClemens/glissando","owner":"ArthurClemens","description":"A simple content slider for anything that needs to move.","archived":false,"fork":false,"pushed_at":"2025-01-15T04:55:05.000Z","size":11430,"stargazers_count":6,"open_issues_count":11,"forks_count":1,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-02-08T19:51:25.469Z","etag":null,"topics":["carousel","g","glissando-mithril","glissando-react","mithriljs","react","slider"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ArthurClemens.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-04-18T11:02:45.000Z","updated_at":"2025-01-15T04:52:15.000Z","dependencies_parsed_at":"2024-04-13T14:05:59.692Z","dependency_job_id":"f44ae170-84fd-4ced-a771-a9fa6fbb6455","html_url":"https://github.com/ArthurClemens/glissando","commit_stats":{"total_commits":497,"total_committers":4,"mean_commits":124.25,"dds":0.2857142857142857,"last_synced_commit":"c6fcb5f836d66aadafd80a7715b8f4254a43e163"},"previous_names":[],"tags_count":18,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ArthurClemens%2Fglissando","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ArthurClemens%2Fglissando/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ArthurClemens%2Fglissando/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ArthurClemens%2Fglissando/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ArthurClemens","download_url":"https://codeload.github.com/ArthurClemens/glissando/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":238306443,"owners_count":19450146,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["carousel","g","glissando-mithril","glissando-react","mithriljs","react","slider"],"created_at":"2025-02-11T14:00:02.299Z","updated_at":"2025-10-26T10:30:28.926Z","avatar_url":"https://github.com/ArthurClemens.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Glissando\n\nA simple content slider for anything that needs to slide.\n\nFor React and Mithril.\n\n- [Features](#features)\n- [Usage, demos and examples](#usage-demos-and-examples)\n- [API](#api)\n  - [Introduction](#introduction)\n    - [Standalone use](#standalone-use)\n    - [Directed use](#directed-use)\n  - [Slider model](#slider-model)\n    - [Initial state](#initial-state)\n      - [Standalone use](#standalone-use-1)\n      - [Directed use](#directed-use-1)\n  - [Slider component](#slider-component)\n    - [Options](#options)\n    - [With React](#with-react)\n      - [Standalone use](#standalone-use-2)\n      - [Directed use](#directed-use-2)\n      - [CSS](#css)\n    - [With Mithril](#with-mithril)\n      - [Standalone use](#standalone-use-3)\n      - [Directed use](#directed-use-3)\n      - [CSS](#css-1)\n  - [Model methods](#model-methods)\n    - [next](#next)\n    - [previous](#previous)\n    - [goTo](#goto)\n    - [hasNext](#hasnext)\n    - [hasPrevious](#hasprevious)\n    - [isAnimating](#isanimating)\n    - [getState](#getstate)\n    - [getLocation](#getlocation)\n    - [getPreviousLocation](#getpreviouslocation)\n    - [getNextLocation](#getnextlocation)\n    - [getChanges](#getchanges)\n- [Helper functions](#helper-functions)\n  - [createLocationsFromPath](#createlocationsfrompath)\n    - [With React](#with-react-1)\n    - [With Mithril](#with-mithril-1)\n- [RTL support](#rtl-support)\n- [Supported browsers](#supported-browsers)\n- [License](#license)\n- [Shout out](#shout-out)\n\n\n## Features\n\n- Efficient rendering: by default only 3 elements are rendered at a single time (the previous, current and next element) (this can be changed).\n- This results in a minimal memory footprint, so safe for mobile.\n- Can be controlled with next/previous actions, jump to page action, with or without animation.\n- Use with a router: use the router location to control the slider. Or use other app state.\n- Query for state, subscribe to changes.\n- The list of elements can be changed on the fly.\n- Right-to-left language support, using mirrored transitions.\n- Written in TypeScript.\n\n\n## Usage, demos and examples\n\n* [Glissando for React](https://github.com/ArthurClemens/glissando/blob/master/packages/glissando-react/README.md)\n* [Glissando for Mithril](https://github.com/ArthurClemens/glissando/blob/master/packages/glissando-mithril/README.md)\n\n\n## API\n\n### Introduction\n\nA glissando slider is created with 2 parts:\n\n1. A **model** that maintains internal state and provides methods to control the slider.\n2. A **slider component** that takes child elements as views. The component informs the model to update, for instance when the children have been changed.\n\nThe slider component can be used standalone or directed.\n\n#### Standalone use\n\nThis is the simplest setup. Use control methods: `next()`, `goTo({ index: 1 })`, etcetera to update the model state.\n \n\n#### Directed use\n\nApplication state is used to control the slider. An example of application state is a router with a unique page URL for each slide.\n\nPass:\n* A list of location ids (for example: possible route paths)\n* The current location id (for example: the current route path)\n\nWhen application state changes the current location id, the slider model will subsequently be updated.\n\nFor example:\n1. The Next button invokes a new URL\n2. The new router path is used to set the location id\n3. With the updated slider state, the slider component will slide to the corresponding element\n\n\nExamples for both uses are shown in the [React](https://github.com/ArthurClemens/glissando/blob/master/packages/glissando-react/README.md) and [Mithril](https://github.com/ArthurClemens/glissando/blob/master/packages/glissando-mithril/README.md) documentation sections.\n\n\n### Slider model\n\n\n```typescript\nconst model: Glissando.Model = useGlissandoModel();\n```\n\n#### Initial state\n\n##### Standalone use\n\n```typescript\nconst initalState: Glissando.InitialState = {\n  // default values:\n  index: 0,\n  sideViews: 1,\n};\nconst model: Glissando.Model = useGlissandoModel(initalState);\n```\n\n| **Parameter** | **Required** | **Type** | **Description**                                                                                                                 |\n| ------------- | ------------ | -------- | ------------------------------------------------------------------------------------------------------------------------------- |\n| **sideViews** | optional     | `number` | Defines how many items are rendered. For value 1: the current, previous and next item. For value 2: one more item at each side. |\n| **index**     | optional     | `number` | The initial location index.                                                                                                     |\n\n\n##### Directed use\n\n```typescript\nconst initalState: Glissando.InitialState = {\n  locations: ['a', 'b', 'c'],\n  location: 'a',\n};\nconst model: Glissando.Model = useGlissandoModel(initalState);\n```\n\n| **Parameter** | **Required** | **Type**   | **Description**                                                                                                                 |\n| ------------- | ------------ | ---------- | ------------------------------------------------------------------------------------------------------------------------------- |\n| **sideViews** | optional     | `number`   | Defines how many items are rendered. For value 1: the current, previous and next item. For value 2: one more item at each side. |\n| **locations** | optional     | `string[]` | A list of location ids, for example: possible route paths.                                                                      |\n| **location**  | optional     | `string`   | The current location id, for example: the current route path.                                                                   |\n\n\n\n\n\n### Slider component\n\nThe GlissandoSlider component receives the model and child elements: the items to slide.\n\nThere is no limit to the number of children. By default only the current, previous and next items are rendered. This can be expanded with initial state attribute `sideViews`.\n\nChildren can be changed dynamically.\n\n#### Options\n\n| **Parameter** | **Required** | **Type**           | **Description**                                                             |\n| ------------- | ------------ | ------------------ | --------------------------------------------------------------------------- |\n| **model**     | required     | `GlissandoModel`   | The slider model                                                            |\n| **children**  | required     | Component children | The elements to slide                                                       |\n| **locations** | optional     | `string[]`         | (directed use) List of location ids, for example: possible route paths      |\n| **location**  | optional     | `string`           | (directed use) The current location id, for example: the current route path |\n| **className** | optional     | `string`           | Extra class name                                                            |\n\n\n#### With React\n\n##### Standalone use\n\n```jsx\nimport { GlissandoSlider, useGlissandoModel } from 'glissando-react';\n\nconst model = useGlissandoModel();\n\n\u003cGlissandoSlider model={model}\u003e\n  \u003cPage1 /\u003e\n  \u003cPage2 /\u003e\n  \u003cPage3 /\u003e\n\u003c/GlissandoSlider\u003e\n```\n\n##### Directed use\n\n```tsx\nconst pages = [\"page-1\", \"page-2\", \"page-3\"];\n\nconst Slider = () =\u003e {\n  const match = useRouteMatch();\n  const currentPage = match.params.page;\n\n  return (\n    \u003cGlissandoSlider model={model} locations={pages} location={currentPage}\u003e\n      {pages.map(id =\u003e {\n        return \u003cPage key={id} location={id} /\u003e;\n      })}\n    \u003c/GlissandoSlider\u003e\n  );\n};\n```\n\nSee also: [Glissando usage with React](https://github.com/ArthurClemens/glissando/blob/master/packages/glissando-react/README.md)\n\n##### CSS\n\nImport GlissandoSlider CSS in your project: \n\n```jsx\nimport 'glissando-react/glissando.min.css'\n```\n\nOr when using PostCSS:\n\n```jsx\nimport 'glissando-react/glissando.global.min.css'\n```\n\n\n#### With Mithril\n\n##### Standalone use\n\n```javascript\nimport { GlissandoSlider, useGlissandoModel } from 'glissando-mithril';\n\nconst model = useGlissandoModel();\n\nm(GlissandoSlider, { model }, [\n  m(Page1),\n  m(Page2),\n  m(Page3),\n]);\n```\n\n##### Directed use\n\n```ts\nconst pages = [\"page-1\", \"page-2\", \"page-3\"];\n\nconst Slider = {\n  view: ({ attrs }) =\u003e {\n    const { model } = attrs;\n    const currentPage = m.route.param('page');\n\n    return m(\n      GlissandoSlider,\n      {\n        model,\n        locations: pages,\n        location: currentPage,\n      },\n      pages.map(id =\u003e\n        m(Page, {\n          key: id,\n          location: id,\n        }),\n      ),\n    );\n  },\n};\n```\n\nSee also: [Glissando usage with Mithril](https://github.com/ArthurClemens/glissando/blob/master/packages/glissando-mithril/README.md)\n\n##### CSS\n\nImport GlissandoSlider CSS in your project: \n\n```js\nimport 'glissando-mithril/glissando.min.css'\n```\n\nOr when using PostCSS:\n\n```js\nimport 'glissando-mithril/glissando.global.min.css'\n```\n\n\n\n\n### Model methods\n\n```typescript\nconst model = useGlissandoModel();\n\nconst {\n  // Control:\n  next,\n  previous,\n  goTo,\n\n  // State:\n  hasNext,\n  hasPrevious,\n  isAnimating,\n  getState,\n  \n  // State (directed use):\n  getLocation,\n  getPreviousLocation,\n  getNextLocation,\n  \n  // Subscribe to changes:\n  getChanges,\n} = model;\n```\n\n\n#### next\n\n_Control_\n\nMoves the slider to the next item. It is not possible to go beyond the last item.\n\nRegular use:\n\n```typescript\nmodel.next();\n```\n\nDisable animation:\n\n```typescript\nmodel.next({ animate: false });\n```\n\n\n#### previous\n\n_Control_\n\nMoves the slider to the previous item. It is not possible to go further back than the first item.\n\nRegular use:\n\n```typescript\nmodel.previous();\n```\n\nDisable animation:\n\n```typescript\nmodel.previous({ animate: false });\n```\n\n\n#### goTo\n\n_Control_\n\nMoves the slider to the indicated index. It is not possible to go further back than the first item, or beyond the last item.\n\nRegular use:\n\n```typescript\nmodel.goTo({\n  index: 1\n});\n```\n\nDisable animation:\n\n```typescript\nmodel.goTo({\n  index: 1,\n  animate: false\n});\n```\n\n\n#### hasNext\n\n_State_\n\nReturns whether it is possible to move the slider to a next position.\n\n```typescript\nconst hasNext: boolean = model.hasNext();\n```\n\n\n#### hasPrevious\n\n_State_\n\nReturns whether it is possible to move the slider to a previous position.\n\n```typescript\nconst hasPrevious: boolean = model.hasPrevious();\n```\n\n\n#### isAnimating\n\n_State_\n\nReturns whether it the slider is currently animating.\n\n```typescript\nconst isAnimating: boolean = model.isAnimating();\n```\n\n\n#### getState\n\n_State_\n\n**As selector**\n\nReturns the state object.\n\n```typescript\nconst state: Glissando.State = model.getState();\nconst index: number = model.getState().index;\n```\n\n**As stream**\n\nSubscribe to the state stream. The map function is called when the model is updated. Note that this includes updates even when the state has not changed. To get notified on changes only, use `getChanges`.\n\n\n```typescript\nmodel.getChanges.map((s: Glissando.State) =\u003e {\n  // ...\n});\n```\n\n\n#### getLocation\n\n_State (directed use)_\n\nReturns the current location id. If no next location exist returns undefined.\n\n```typescript\nconst location: string = getLocation();\n```\n\n\n#### getPreviousLocation\n\n_State (directed use)_\n\nReturns the previous location id. If no previous location exist returns undefined.\n\n```typescript\nconst previousLocation: string = getPreviousLocation();\n```\n\n\n#### getNextLocation\n\n_State (directed use)_\n\nReturns the next location id. If no next location exist returns undefined.\n\n```typescript\nconst nextLocation: string = getNextLocation();\n```\n\n\n#### getChanges\n\n_Subscribe to changes_\n\nSubscribe to the changed state stream. The map function is called when the model is updated and the new state differs from the previous state.\n\n```typescript\nmodel.getChanges\n  .map((state: Glissando.State) =\u003e {\n    // ...\n  })\n```\n\nWhen calling `getChanges` in the component's render loop (in React's function component and in Mithril's view function, add `end(true)` to stop listening to the stream:\n\n```typescript\nmodel.getChanges\n  .map((state: Glissando.State) =\u003e {\n    // ...\n  })\n  .end(true); // prevent accumulation of stream subscriptions\n```\n\nWhen calling `getChanges` in Mithril's closure component (outside of `view`), do not end the stream.\n\n\n## Helper functions\n\nHelper functions are provided in separate package `glissando-helpers`.\n\n\n### createLocationsFromPath\n\nHelper function to create the list of locations (and the current location) from a path.\nThis is useful when traversing a hierarchical path, such as a master detail pattern (for example a list of posts each linked to a post page, and possibly deeper levels).\n\n`createLocationsFromPath` creates a breadcrumb trail from a given path and returns a new list of locations based on the merge of the breadcrumb trail and the current model locations.\n\nFrom path: `\"/users/Ferdinand/details\"`, the generated locations will be: `[\"/users\", \"/users/Ferdinand\", \"/users/Ferdinand/details\"]`. When this list of locations is fed to the Glissando component, back and forward links will be set automatically. \n  \n#### With React\n\n```typescript\nimport {\n  Glissando,\n  GlissandoSlider,\n  useGlissandoModel,\n} from 'glissando-react';\nimport {\n  createLocationsFromPath\n} from 'glissando-helpers';\nimport { useRouteMatch } from 'react-router-dom';\n\n// in component:\nconst model = useGlissandoModel();\n\nconst match = useRouteMatch();\n\nconst location = match.url;\nconst locations = createLocationsFromPath(\n  location,\n  model.getState().locations,\n);\n\n// Call GlissandoSlider component with locations and location\n```\n#### With Mithril\n\n```typescript\nimport {\n  Glissando,\n  GlissandoSlider,\n  useGlissandoModel,\n} from 'glissando-mithril';\nimport {\n  createLocationsFromPath\n} from 'glissando-helpers';\n\n// in component:\nconst model = useGlissandoModel();\n\nconst location = m.route.get();\n\nconst locations = createLocationsFromPath(\n  location,\n  model.getState().locations,\n);\n\n// Call GlissandoSlider component with locations and location\n```\n\n## RTL support\n\nGlissando automatically detects the reading direction. Set one of the parent's HTML attribute `direction` to `\"rtl\"`.\n\n\n## Supported browsers\n\nGlissando is tested on major browsers, Edge and Internet Explorer 11. \n\n\n\n## License\n\nMIT\n\n\n\n## Shout out\n\nGlissando uses the [Meiosis state pattern](http://meiosis.js.org/) for state management.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Farthurclemens%2Fglissando","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Farthurclemens%2Fglissando","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Farthurclemens%2Fglissando/lists"}